├── .gitignore ├── Ghidra-Scripts ├── Clear_All_Instruction_Colors.py ├── Highlight_Target_Instructions.py ├── LICENSE ├── Label_Dynamically_Resolved_Iat_Entries.py ├── Minimize_Automatic_Function_Comments.py ├── Preview_Function_Capabilities.py ├── README.md └── Utils.py ├── LICENSE ├── NetworkExamples ├── ArduinoHttpsClient │ └── ArduinoHttpsClient.ino ├── BallDropClient │ └── readme.md ├── BallDropEthernetJoystickClient │ └── readme.md ├── BallDropServer │ └── readme.md ├── BallDropWifi101JoystickClient │ └── readme.md ├── BallDropWifiJoystickClient │ └── readme.md ├── BridgeCurlClient │ └── readme.md ├── BridgeJoystickClient │ └── readme.md ├── BridgeRestAccelerometer │ └── readme.md ├── BridgeRestParser │ └── readme.md ├── BridgeRestPut │ └── readme.md ├── BridgeRestRGB │ └── readme.md ├── BridgeSocket │ └── readme.md ├── BridgeTelnetClient │ └── readme.md ├── BridgeToDweet │ └── readme.md ├── BridgeToNode │ └── readme.md ├── ExpressBasics │ ├── index.html │ ├── index.js │ ├── js │ │ └── zepto.min.js │ ├── package.json │ └── readme.md ├── JSClientThermostat │ ├── index.html │ ├── style.css │ └── thermostat.js ├── JSClock │ └── index.html ├── README.md ├── nodeImap │ ├── accounts.js │ └── index.js ├── nodeOpenWindow │ └── readme.md ├── nodeRestToSerial │ ├── README.md │ ├── RGBLEDControl │ │ └── RGBLEDControl.ino │ ├── index.js │ ├── npm-debug.log │ ├── package.json │ └── public │ │ └── index.html ├── nodeSerialIntro │ └── README.md ├── nodeSerialToJSON │ ├── ADXL326 │ │ └── ADXL326.ino │ ├── Joystick │ │ └── Joystick.ino │ ├── README.md │ ├── index.html │ ├── index.js │ └── package.json ├── nodeSerialToRest │ ├── ArduinoSerialParse │ │ └── ArduinoSerialParse.ino │ ├── index.js │ ├── package.json │ └── public │ │ └── index.html ├── nodeSimpleServer │ └── readme.md ├── nodeThermostat │ ├── css │ │ └── style.css │ ├── index.html │ ├── index.js │ ├── js │ │ └── thermostat.js │ ├── package.json │ └── thermostat │ │ └── thermostat.ino ├── nodeToBluetoothSerial │ ├── css │ │ └── style.css │ ├── index.html │ ├── index.js │ ├── js │ │ ├── buttonControls.js │ │ └── zepto.min.js │ └── package.json ├── nodeToFile │ └── readme.md ├── nodeToProcessing │ ├── ADXL326 │ │ └── ADXL326.ino │ ├── README.md │ ├── index.js │ ├── jsonProcessing │ │ └── jsonProcessing.pde │ └── package.json └── nodeTraceroute │ └── readme.md ├── Networking-Scripts ├── C2_Simulator_Http_Server.py ├── C2_Simulator_Tcp_Client.py ├── C2_Simulator_Tcp_Server.py └── README.md ├── README.md ├── code-of-conduct.md ├── contributing.md ├── img ├── 625x403.png ├── cloud1.png ├── dhcp.png ├── dns.png ├── ftp.png └── network.png └── python-scripts-for-network-engineers ├── LICENSE ├── README.md ├── backup-multiple-routers.py ├── backup-router.py ├── device-types.py ├── devices.txt ├── netmiko-save-config.py ├── ping-trace.py ├── ping.py ├── ssh-to-multiple-routers.py └── ssh-to-router.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /Ghidra-Scripts/Clear_All_Instruction_Colors.py: -------------------------------------------------------------------------------- 1 | # Clears all colors applied to instructions in program 2 | #@author https://AGDCServices.com 3 | #@category AGDCservices 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | 8 | ''' 9 | Removes all highlight colors from current program. 10 | Applied highlighting colors are saved with the ghidra file. 11 | This script can be used to remove the colors prior to exporting 12 | and sharing the ghidra database so that the highlight colors 13 | don't clash with different color schemes used by coworkers 14 | ''' 15 | 16 | instructions = currentProgram.getListing().getInstructions(True) 17 | for curInstr in instructions: 18 | clearBackgroundColor(curInstr.getAddress()) 19 | -------------------------------------------------------------------------------- /Ghidra-Scripts/Highlight_Target_Instructions.py: -------------------------------------------------------------------------------- 1 | # Highlights target instructions using custom colors for easy identification 2 | #@author https://AGDCServices.com 3 | #@category AGDCservices 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | 8 | ''' 9 | Script will search all instructions in current program 10 | looking for target instructions of interest. When found, 11 | a defined highlighting color will be applied to make it 12 | easy to identify target instructions. 13 | 14 | default color choices are made to work with the 15 | AGDC_codeBrowser_14.tool. They can be changed to fit any 16 | coloring schema by modifying the defined color constants 17 | at the top of the program 18 | ''' 19 | 20 | from java.awt import Color 21 | 22 | 23 | # define RGB colors for target instructions 24 | 25 | # color_default sets non-target instructions colors 26 | # needed to account for bug in graph view 27 | COLOR_DEFAULT = Color(255,255,255) # white 28 | COLOR_CALL = Color(255, 220, 220) #light red 29 | COLOR_POINTER = Color(200, 240, 255) # blue 30 | COLOR_CRYPTO = Color(245, 205, 255) # violet 31 | COLOR_STRING_OPERATION = Color(180,230,170) # green 32 | 33 | # 34 | # additional unused colors 35 | # 36 | # Color(255,255,180) #yellow 37 | # Color(220,255,200) #very light green 38 | # Color(255,200,100) #orange 39 | # Color(220, 220, 220) #light grey 40 | # Color(195, 195, 195) # dark grey 41 | 42 | 43 | 44 | REG_TYPE = 512 45 | 46 | 47 | # loop through all program instructions searching 48 | # for target instructions. when found, apply defined 49 | # color 50 | instructions = currentProgram.getListing().getInstructions(True) 51 | for curInstr in instructions: 52 | 53 | bIsTargetInstruction = False 54 | 55 | curMnem = curInstr.getMnemonicString().lower() 56 | 57 | # color call instructions 58 | if curMnem == 'call': 59 | bIsTargetInstruction = True 60 | setBackgroundColor(curInstr.getAddress(), COLOR_CALL) 61 | 62 | 63 | # color lea instructions 64 | if curMnem == 'lea': 65 | bIsTargetInstruction = True 66 | setBackgroundColor(curInstr.getAddress(), COLOR_POINTER) 67 | 68 | 69 | # 70 | # color suspected crypto instructions 71 | # 72 | 73 | # xor that does not zero out the register 74 | if (curMnem == 'xor') and (curInstr.getOpObjects(0) != curInstr.getOpObjects(1)): 75 | bIsTargetInstruction = True 76 | setBackgroundColor(curInstr.getAddress(), COLOR_CRYPTO) 77 | 78 | 79 | # common RC4 instructions 80 | if (curMnem == 'cmp') and (curInstr.getOperandType(0) == REG_TYPE) and (curInstr.getOpObjects(1)[0].toString() == '0x100'): 81 | bIsTargetInstruction = True 82 | setBackgroundColor(curInstr.getAddress(), COLOR_CRYPTO) 83 | 84 | # misc math operations 85 | mathInstrList = ['sar', 'sal', 'shr', 'shl', 'ror', 'rol', 'idiv', 'div', 'imul', 'mul', 'not'] 86 | if curMnem in mathInstrList: 87 | bIsTargetInstruction = True 88 | setBackgroundColor(curInstr.getAddress(), COLOR_CRYPTO) 89 | 90 | 91 | # 92 | # 93 | # 94 | 95 | 96 | 97 | # color string operations 98 | # skip instructions that start with 'c' to exclude conditional moves, e.g. cmovs 99 | if (curMnem.startswith('c') == False) and (curMnem.endswith('x') == False) and ( ('scas' in curMnem) or ('movs' in curMnem) or ('stos' in curMnem) ): 100 | bIsTargetInstruction = True 101 | setBackgroundColor(curInstr.getAddress(), COLOR_STRING_OPERATION) 102 | 103 | 104 | 105 | 106 | # fixes ghidra bug in graph mode where if a color is applied to the first instruction of a code block 107 | # the color will also be applied to the rest of the instructions in that code block 108 | # by setting the color to every line that's not a target instruction to the default color, 109 | # target colors should be applied accurately 110 | # error only appears to be in graph view. colors will be correctly applied in flat view, but incorrect in graph view 111 | # if you just clear the colors instead of setting all the colors to the default color, 112 | # the error will still occur. In this case, it may get fixed by redrawing the graph, 113 | # but you will have to redraw the graph every time you come across an error 114 | if bIsTargetInstruction == False: 115 | setBackgroundColor(curInstr.getAddress(), COLOR_DEFAULT) 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /Ghidra-Scripts/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Ghidra-Scripts/Label_Dynamically_Resolved_Iat_Entries.py: -------------------------------------------------------------------------------- 1 | #Find dynamically resolved IAT locations and apply labels from input file 2 | #@author https://AGDCServices.com 3 | #@category AGDCservices 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | #@toolbar 8 | 9 | ''' 10 | Script will search program for all dynamically resolved 11 | imports and label them with the appropriate API name pulled 12 | from a provided labeled IAT dump file. Only resolved imports 13 | stored in global variables will be identified. This script will 14 | not label every resolved global variable, but only those that 15 | are used inside a call instruction 16 | 17 | The labeled IAT dump file must be generated by an associated 18 | program, "Dump_Labeled_Iat_Memory.exe". This program is located 19 | in another repo on this github site called "Misc Malware Anaysis Tools" 20 | 21 | usage: 22 | Run file inside a debugger up to the point where all 23 | dynamically resolved imports are resolved. At that point, 24 | run the associated "Dump_Labeled_Iat_Memory.exe" to create 25 | the labeled Iat dump file. 26 | 27 | Once you have the labeled IAT dump file, run this script. 28 | The script must be run prior to renaming any of the global 29 | IAT variables. The script will not overwrite any manually 30 | named global variables. 31 | 32 | ''' 33 | 34 | 35 | def main(): 36 | 37 | try: 38 | fileObject = askFile('Select Labeled Iat Dump File', 'Open') 39 | except: 40 | print('file could not be opened') 41 | quit() 42 | 43 | iatList = Get_Dynamically_Resolved_Iat_Addresses() 44 | Label_Dynamically_Resolved_Iat_Addresses(iatList, fileObject.getPath()) 45 | 46 | 47 | def Get_Dynamically_Resolved_Iat_Addresses(): 48 | ''' 49 | function will search current program for all 50 | calls to unresolved global variables and return 51 | a list of all the global variable addresses. 52 | ''' 53 | 54 | instructions = currentProgram.getListing().getInstructions(True) 55 | iatSet = set() 56 | for curInstr in instructions: 57 | curMnem = curInstr.getMnemonicString().lower() 58 | if curMnem == 'call': 59 | operandRef = curInstr.getOperandReferences(0) 60 | if len(operandRef) != 0: 61 | operandRefEa = operandRef[0].getToAddress() 62 | curLabel = getSymbolAt(operandRefEa) 63 | if curLabel != None: # accounts for non memory references 64 | if curLabel.getName().lower().startswith( ('dat_', 'byte_', 'word_', 'dword_', 'qword_') ): 65 | iatSet.add(operandRefEa) 66 | 67 | 68 | return list(iatSet) 69 | 70 | 71 | def Label_Dynamically_Resolved_Iat_Addresses(iatList, labeledIatDumpFileName): 72 | ''' 73 | function will read in file with a format of: 74 | iatRva\tapiString 75 | each address in the iatList will be checked to 76 | see if there is an entry in the labeled Iat Dump File. 77 | If so, the iat label will be set to the api string 78 | from the input file 79 | 80 | iatList should be list of address objects 81 | ''' 82 | 83 | with open(labeledIatDumpFileName, 'r') as fp: 84 | labeledIatList = fp.read().splitlines() 85 | 86 | imageBase = currentProgram.getImageBase().getOffset() 87 | labeledIatDict = dict() 88 | for i in labeledIatList: 89 | curRva, curIatLabel = i.split('\t') 90 | labeledIatDict[imageBase + int(curRva, 16)] = curIatLabel 91 | 92 | labeledCount = 0 93 | unresolvedList = [] 94 | for entry in iatList: 95 | curIatLabel = labeledIatDict.get(entry.getOffset(), None) 96 | if curIatLabel != None: 97 | getSymbolAt(entry).setName(curIatLabel, ghidra.program.model.symbol.SourceType.USER_DEFINED) 98 | labeledCount += 1 99 | else: 100 | unresolvedList.append('could not resolve address 0x{:x}'.format(entry.getOffset())) 101 | 102 | print('labeled {:x} dynamically resolved IAT entries'.format(labeledCount)) 103 | 104 | if len(unresolvedList) != 0: 105 | print('[*] ERROR, was not able to resolve {:x} entries'.format(len(unresolvedList))) 106 | print('\n'.join(unresolvedList)) 107 | 108 | 109 | 110 | 111 | 112 | if __name__ == '__main__': 113 | main() -------------------------------------------------------------------------------- /Ghidra-Scripts/Minimize_Automatic_Function_Comments.py: -------------------------------------------------------------------------------- 1 | # Adds a short repeatable comment to all functions to hide the automatic function comment 2 | #@author https://AGDCServices.com 3 | #@category AGDCservices 4 | #@keybinding 5 | #@menupath 6 | #@toolbar 7 | 8 | ''' 9 | Adds a single space as a repeatable comment to all functions 10 | within the current program. By default, Ghidra adds a function 11 | prototype as a repeatable comment to all functions. These comments 12 | are very long which will force the code block to expand it its maximum 13 | size within the graph view. These default comments do not add any real value 14 | and decreases the amount of code that can be seen in the graph view. 15 | 16 | Currently, there is no way to turn this option off. A work around is 17 | to replace the repeatable comment with a single space so that you don't 18 | see any comment by default, and the code block is not expanded out to 19 | it's maximum size because of the long function prototype comment. 20 | ''' 21 | 22 | REPEATABLE_COMMENT = ghidra.program.model.listing.CodeUnit.REPEATABLE_COMMENT 23 | listing = currentProgram.getListing() 24 | 25 | commentCount = 0 26 | for func in listing.getFunctions(True): 27 | listing.getCodeUnitAt(func.getEntryPoint()).setComment(REPEATABLE_COMMENT, ' ') 28 | commentCount += 1 29 | 30 | print('Set {:d} repeatable function comments to a single space to prevent automatic function comments from being displayd'.format(commentCount)) -------------------------------------------------------------------------------- /Ghidra-Scripts/README.md: -------------------------------------------------------------------------------- 1 | # Ghidra Scripts 2 | Custom scripts to make analyzing malware easier in Ghidra 3 | ## Installation 4 | Add these scripts to your Ghidra scripts directory: 5 | 1. Open any file in Ghidra for analysis 6 | 2. Select the Window / Script Manager menu 7 | 3. Click the "Script Directories" icon in the upper right toolbar 8 | 4. Add the directory where your scripts are located via the green plus sign 9 | 5. All scripts will show up under the AGDCservices folder 10 | ## Clear_All_Instruction_Colors.py 11 | Removes all highlight colors from current program. Applied highlighting colors are saved with the ghidra file. 12 | This script can be used to remove the colors prior to exporting and sharing the ghidra database so that the highlight colors don't clash with different color schemes used by coworkers. See script header for more usage details. 13 | ## Preview_Function_Capabilities.py 14 | This script will name all unidentified functions with a nomenclature that provides a preview of important capabilities included within the function and all child functions. 15 | 16 | The script includes a list of hardcoded important API calls. The script will locate all calls contained in the unidentifed function and it's children functions. For any of the calls which match the hardcoded API call list, a shorthand name will be applied to indicate which category of important call is contained within the function. 17 | 18 | The naming nomenclature is based on capability and does not identify specific API's. By keeping the syntax short and just for capability, you can get a preview of all the important capabilities within a function without having the name get enormous. See script header for more details. 19 | 20 | For a video demonstration of this script, view the video "Ghidra Script To Name Function From Capabilities" on the AGDC Services channel of youtube, https://youtu.be/s5weitGaKLw 21 | ## Highlight_Target_Instructions.py 22 | Script to search all instructions in current program looking for target instructions of interest. When found, 23 | a defined highlighting color will be applied to make it easy to identify target instructions. Target instructions are things like call instructions, potential crypto operations, pointer instructions, etc. Highlighting instructions of interest decrease the chance of missing important instructions when skimming malware code. See script header for more usage details. 24 | 25 | **Default color choices are made to work with the AGDC_codeBrowser_##.tool. They can be changed to fit any coloring schema by modifying the defined color constants at the top of the script** 26 | ## Minimize_Automatic_Function_Comments.py 27 | Adds a single space as a repeatable comment to all functions within the current program. By default, Ghidra adds a function prototype as a repeatable comment to all functions. These comments are very long which will force the code block to expand it its maximum size within the graph view. These default comments do not add any real value and decreases the amount of code that can be seen in the graph view. 28 | 29 | Currently, there is no way to turn this option off. A work around is to replace the repeatable comment with a single space so that you don't see any comment by default, and the code block is not expanded out to 30 | it's maximum size because of the long function prototype comment. See script header for more usage details. 31 | ## Utils.py 32 | A number of commonly used convenience functions to aid in rapid scripting, e.g. Get_Operand_As_Immediate_Value, Get_Next_Target_Instruction, Get_Bytes_List, etc. See script header for more usage details. 33 | ## Label_Dynamically_Resolved_Iat_Entries.py 34 | Script to aid in reverse engineering files that dynamically resolve imports. Script will search program for all dynamically resolved imports and label them with the appropriate API name pulled from a provided labeled IAT dump file. Only resolved imports stored in global variables will be identified. This script will not label every resolved global variable, but only those that are used inside a call instruction. 35 | 36 | The labeled IAT dump file must be generated by an associated program, "Dump_Labeled_Iat_Memory.exe". This program is located in another repo on this github site called "Misc Malware Anaysis Tools". See script header for more usage details. 37 | 38 | -------------------------------------------------------------------------------- /Ghidra-Scripts/Utils.py: -------------------------------------------------------------------------------- 1 | from __main__ import * 2 | 3 | ''' 4 | Utility module of common helper functions used 5 | in building Ghidra scripts 6 | 7 | Contained function prototypes below: 8 | Get_Bytes_List(targetEa, nLen) 9 | Get_Bytes_String(targetEa, nLen) 10 | Get_Ascii_String(targetEa) 11 | Get_Call_Xrefs_To(targetEa) 12 | Get_Prev_Target_Instruction(curInstr, mnem, N, MAX_INSTRUCTIONS = 9999) 13 | Get_Next_Target_Instruction(curInstr, mnem, N, MAX_INSTRUCTIONS = 9999) 14 | Get_Operand_As_Address(targetInstr, operandIndex) 15 | Get_Operand_As_Immediate_Value(targetInstr, operandIndex) 16 | Get_Operand_As_String(targetInstr, operandIndex) 17 | 18 | ''' 19 | 20 | def Get_Bytes_List(targetEa, nLen): 21 | ''' 22 | gets the bytes from memory, treating as unsigned bytes 23 | ghidra treats read bytes as signed which is not what 24 | you normally want when reading memory, e.g. if you call 25 | getBytes on a byte 0xfe, you won't get 0xfe, you'll get -2 26 | this may not be an issue depending on what operation you 27 | are performing, or it may, e.g. reading a byte that is 28 | displayed as a negative value will fail when compared to 29 | the two's complement hex (-2 != 0xfe). If you're using 30 | the byte to patch the program, it may work ok. 31 | 32 | returns result as a list 33 | ''' 34 | 35 | signedList = list(getBytes(targetEa, nLen)) 36 | unsignedList = [] 37 | for curByte in signedList: 38 | if curByte < 0: 39 | uByte = (0xff - abs(curByte) + 1) 40 | else: 41 | uByte= curByte 42 | unsignedList.append(uByte) 43 | 44 | return unsignedList 45 | 46 | def Get_Bytes_String(targetEa, nLen): 47 | ''' 48 | gets the bytes from memory, treating as unsigned bytes 49 | ghidra treats read bytes as signed which is not what 50 | you normally want when reading memory, e.g. if you call 51 | getBytes on a byte 0xfe, you won't get 0xfe, you'll get -2 52 | this may not be an issue depending on what operation you 53 | are performing, or it may, e.g. reading a byte that is 54 | displayed as a negative value will fail when compared to 55 | the two's complement hex (-2 != 0xfe). If you're using 56 | the byte to patch the program, it may work ok. 57 | 58 | returns result as a string 59 | ''' 60 | 61 | signedList = list(getBytes(targetEa, nLen)) 62 | unsignedList = [] 63 | for curByte in signedList: 64 | if curByte < 0: 65 | uByte = (0xff - abs(curByte) + 1) 66 | else: 67 | uByte= curByte 68 | unsignedList.append(chr(uByte)) 69 | 70 | return ''.join(unsignedList) 71 | 72 | 73 | def Get_Ascii_String(targetEa): 74 | ''' 75 | returns the null terminated ascii string starting 76 | at targetEa. Returns a string object and does not 77 | include the terminating null character 78 | 79 | targetEa must be an address object 80 | ''' 81 | 82 | result = '' 83 | i = 0 84 | while True: 85 | curByte = chr(getByte(targetEa.add(i))) 86 | if curByte == chr(0): break 87 | result += curByte 88 | i += 1 89 | 90 | return result 91 | 92 | def Get_Call_Xrefs_To(targetEa): 93 | ''' 94 | returns list of addresses which call the targetEa 95 | 96 | ''' 97 | 98 | callEaList = [] 99 | for ref in getReferencesTo(targetEa): 100 | if getInstructionAt(ref.getFromAddress()).getMnemonicString().lower() == 'call': 101 | callEaList.append(ref.getFromAddress()) 102 | 103 | return callEaList 104 | 105 | def Get_Prev_Target_Instruction(curInstr, mnem, N, MAX_INSTRUCTIONS = 9999): 106 | ''' 107 | gets N'th previous target instruction from the curInstr 108 | function will only go back MAX_INSTRUCTIONS 109 | function will not search outside of current function if the 110 | current instruction is inside a defined function 111 | returns None on failure 112 | ''' 113 | 114 | 115 | # get address set of current function to use in determining if prev instruction 116 | # is outside of current function 117 | try: 118 | funcBody = getFunctionContaining(curInstr.getAddress()).getBody() 119 | except: 120 | funcBody = None 121 | 122 | 123 | # get Nth prev instruction 124 | totalInstructionCount = 0 125 | targetInstructionCount = 0 126 | while (totalInstructionCount < MAX_INSTRUCTIONS) and (targetInstructionCount < N): 127 | curInstr = curInstr.getPrevious() 128 | 129 | if curInstr == None: break 130 | if funcBody != None: 131 | if funcBody.contains(curInstr.getAddress()) == False: break 132 | 133 | if curInstr.getMnemonicString().lower() == mnem.lower(): targetInstructionCount += 1 134 | 135 | totalInstructionCount += 1 136 | 137 | 138 | # return the results 139 | if targetInstructionCount == N: 140 | result = curInstr 141 | else: 142 | result = None 143 | 144 | return result 145 | 146 | def Get_Next_Target_Instruction(curInstr, mnem, N, MAX_INSTRUCTIONS = 9999): 147 | ''' 148 | gets N'th next target instruction from the curInstr 149 | function will only go forward MAX_INSTRUCTIONS 150 | function will not search outside of current function if the 151 | current instruction is inside defined function 152 | returns None on failure 153 | ''' 154 | 155 | # get address set of current function to use in determining if prev instruction 156 | # is outside of current function 157 | try: 158 | funcBody = getFunctionContaining(curInstr.getAddress()).getBody() 159 | except: 160 | funcBody = None 161 | 162 | 163 | # get Nth next instruction 164 | totalInstructionCount = 0 165 | targetInstructionCount = 0 166 | while (totalInstructionCount < MAX_INSTRUCTIONS) and (targetInstructionCount < N): 167 | curInstr = curInstr.getNext() 168 | 169 | if curInstr == None: break 170 | if funcBody != None: 171 | if funcBody.contains(curInstr.getAddress()) == False: break 172 | 173 | if curInstr.getMnemonicString().lower() == mnem.lower(): targetInstructionCount += 1 174 | 175 | totalInstructionCount += 1 176 | 177 | 178 | # return the results 179 | if targetInstructionCount == N: 180 | result = curInstr 181 | else: 182 | result = None 183 | 184 | return result 185 | 186 | def Get_Operand_As_Address(targetInstr, operandIndex): 187 | ''' 188 | returns the value for the operandIndex operand of the 189 | target instruction treated as an address. if the 190 | target operand can not be treated as an address, 191 | returns None. operandIndex starts at 0 192 | 193 | If this is called on jumps or calls, the final 194 | address jumped to / called will be returned 195 | 196 | There are no real checks for validity and it's up to 197 | the author to ensure the target operand should be an address 198 | 199 | ''' 200 | 201 | # error check 202 | if operandIndex >= targetInstr.getNumOperands(): 203 | print('[*] Error in Get_Operand_As_Address. operandIndex is too large at {:s}'.format(targetInstr.getAddress().toString())) 204 | return None 205 | elif targetInstr.getNumOperands() == 0: 206 | return None 207 | 208 | 209 | operand = targetInstr.getOpObjects(operandIndex)[0] 210 | if type(operand) == ghidra.program.model.scalar.Scalar: 211 | targetValue = toAddr(operand.getValue()) 212 | elif type(operand) == ghidra.program.model.address.GenericAddress: 213 | targetValue = operand 214 | else: 215 | targetValue = None 216 | 217 | return targetValue 218 | 219 | def Get_Operand_As_Immediate_Value(targetInstr, operandIndex): 220 | ''' 221 | returns the value for the operandIndex operand of the target instruction 222 | if the target operand is not an immediate value, the function will attempt 223 | to find where the variable was previously set. It will ONLY search within 224 | the current function to find where the variable was previously set. 225 | if operand value can not be determined, returns None 226 | operandIndex starts at 0 227 | ''' 228 | 229 | # operand types are typically different if operand is 230 | # used in a call versus not a call and if there is a 231 | # reference or not 232 | OP_TYPE_IMMEDIATE = 16384 233 | OP_TYPE_NO_CALL_REG = 512 234 | OP_TYPE_NO_CALL_STACK = 4202496 235 | # global variables have numerous reference types 236 | # unsure how to differentiate the different types 237 | 238 | 239 | # error check 240 | if operandIndex >= targetInstr.getNumOperands(): 241 | print('[*] Error in Get_Operand_As_Immediate_Value. operandIndex is too large at {:s}'.format(targetInstr.getAddress().toString())) 242 | return None 243 | elif targetInstr.getNumOperands() == 0: 244 | return None 245 | 246 | 247 | # get address set of current function to use in determining 248 | # if prev instruction is outside of current function 249 | try: 250 | funcBody = getFunctionContaining(targetInstr.getAddress()).getBody() 251 | except: 252 | funcBody = None 253 | 254 | 255 | # find the actual operand value 256 | targetValue = None 257 | opType = targetInstr.getOperandType(operandIndex) 258 | # if operand is a direct number 259 | if opType == OP_TYPE_IMMEDIATE: 260 | targetValue = targetInstr.getOpObjects(operandIndex)[0].getValue() 261 | # else if operand is a register 262 | elif opType == OP_TYPE_NO_CALL_REG: 263 | regName = targetInstr.getOpObjects(operandIndex)[0].getName().lower() 264 | 265 | # search for previous location where register value was set 266 | curInstr = targetInstr 267 | while True: 268 | curInstr = curInstr.getPrevious() 269 | 270 | # check to make sure curInstr is valid 271 | if curInstr == None: break 272 | if funcBody != None: 273 | if funcBody.contains(curInstr.getAddress()) == False: break 274 | 275 | # check different variations of how register values get set 276 | curMnem = curInstr.getMnemonicString().lower() 277 | if (curMnem == 'mov') and (curInstr.getOperandType(0) == OP_TYPE_NO_CALL_REG): 278 | if curInstr.getOpObjects(0)[0].getName().lower() == regName: 279 | if curInstr.getOperandType(1) == OP_TYPE_IMMEDIATE: 280 | targetValue = curInstr.getOpObjects(1)[0].getValue() 281 | elif curInstr.getOperandType(1) == OP_TYPE_NO_CALL_REG: 282 | targetValue = Get_Operand_As_Immediate_Value(curInstr, 1) 283 | break 284 | elif (curMnem == 'xor'): 285 | operand1 = curInstr.getOpObjects(0)[0] 286 | operand2 = curInstr.getOpObjects(1)[0] 287 | op1Type = curInstr.getOperandType(0) 288 | op2Type = curInstr.getOperandType(1) 289 | 290 | if (op1Type == OP_TYPE_NO_CALL_REG) and (op2Type == OP_TYPE_NO_CALL_REG): 291 | if (operand1.getName().lower() == regName) and (operand2.getName().lower() == regName): 292 | targetValue = 0 293 | break 294 | elif (curMnem == 'pop') and (curInstr.getOperandType(0) == OP_TYPE_NO_CALL_REG): 295 | if curInstr.getOpObjects(0)[0].getName().lower() == regName: 296 | # find previous push 297 | # NOTE: assumes previous push corresponds to pop but 298 | # will fail if there is a function call in-between 299 | tmpCurInstr = curInstr.getPrevious() 300 | while True: 301 | # check to make sure tmpCurInstr is valid 302 | if tmpCurInstr == None: break 303 | if funcBody != None: 304 | if funcBody.contains(tmpCurInstr.getAddress()) == False: break 305 | 306 | if tmpCurInstr.getMnemonicString().lower() == 'push': 307 | if tmpCurInstr.getOperandType(0) == OP_TYPE_IMMEDIATE: 308 | targetValue = tmpCurInstr.getOpObjects(0)[0].getValue() 309 | break 310 | 311 | # break out of outer while loop 312 | break 313 | # if operand is a stack variable 314 | elif opType == OP_TYPE_NO_CALL_STACK: 315 | stackOffset = targetInstr.getOperandReferences(operandIndex)[0].getStackOffset() 316 | 317 | # search for previous location where stack variable value was set 318 | curInstr = targetInstr 319 | while True: 320 | curInstr = curInstr.getPrevious() 321 | 322 | # check to make sure curInstr is valid 323 | if curInstr == None: break 324 | if funcBody != None: 325 | if funcBody.contains(curInstr.getAddress()) == False: break 326 | 327 | # find where stack variable was set 328 | curMnem = curInstr.getMnemonicString().lower() 329 | if (curMnem == 'mov') and (curInstr.getOperandType(0) == OP_TYPE_NO_CALL_STACK): 330 | if curInstr.getOperandReferences(0)[0].getStackOffset() == stackOffset: 331 | if curInstr.getOperandType(1) == OP_TYPE_IMMEDIATE: 332 | targetValue = curInstr.getOpObjects(1)[0].getValue() 333 | break 334 | 335 | 336 | 337 | 338 | return targetValue 339 | 340 | def Get_Operand_As_String(targetInstr, operandIndex): 341 | ''' 342 | returns the value for the operandIndex operand of the 343 | target instruction treated as a string. 344 | operandIndex starts at 0 345 | 346 | If this is called on jumps or calls, the final 347 | address jumped to / called will be returned 348 | 349 | ''' 350 | 351 | # error check 352 | if operandIndex >= targetInstr.getNumOperands(): 353 | print('[*] Error in Get_Operand_As_String. operandIndex is too large at {:s}'.format(targetInstr.getAddress().toString())) 354 | return None 355 | elif targetInstr.getNumOperands() == 0: 356 | return None 357 | 358 | 359 | operand = targetInstr.getOpObjects(operandIndex)[0] 360 | 361 | return operand.toString() 362 | 363 | 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NetworkExamples/ArduinoHttpsClient/ArduinoHttpsClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Test HTTP Client 3 | Context: Arduino, with WINC1500 module 4 | */ 5 | // include required libraries and config files 6 | #include 7 | #include 8 | #include 9 | #include "config.h" 10 | 11 | WiFiSSLClient netSocket; // network socket to server 12 | const char server[] = "tigoe.com"; // server name 13 | String route = "/foo"; // API route 14 | 15 | void setup() { 16 | Serial.begin(9600); // initialize serial communication 17 | 18 | // while you're not connected to a WiFi AP, 19 | while ( WiFi.status() != WL_CONNECTED) { 20 | Serial.print("Attempting to connect to Network named: "); 21 | Serial.println(ssid); // print the network name (SSID) 22 | WiFi.begin(ssid, pass); // try to connect 23 | delay(2000); 24 | } 25 | 26 | // When you're connected, print out the device's network status: 27 | IPAddress ip = WiFi.localIP(); 28 | Serial.print("IP Address: "); 29 | Serial.println(ip); 30 | } 31 | 32 | void loop() { 33 | HttpClient http(netSocket, server, 443); // make an HTTP client 34 | http.get(route); // make a GET request 35 | 36 | while (http.connected()) { // while connected to the server, 37 | if (http.available()) { // if there is a response from the server, 38 | String result = http.readString(); // read it 39 | Serial.print(result); // and print it 40 | } 41 | } 42 | // when there's nothing left to the response, 43 | http.stop(); // close the request 44 | delay(1000); // wait 10 seconds 45 | } 46 | 47 | -------------------------------------------------------------------------------- /NetworkExamples/BallDropClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to by the [BallDropGame repository](https://github.com/tigoe/BallDropGame) 2 | -------------------------------------------------------------------------------- /NetworkExamples/BallDropEthernetJoystickClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to by the [BallDropGame repository](https://github.com/tigoe/BallDropGame) 2 | -------------------------------------------------------------------------------- /NetworkExamples/BallDropServer/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to by the [BallDropGame repository](https://github.com/tigoe/BallDropGame) 2 | -------------------------------------------------------------------------------- /NetworkExamples/BallDropWifi101JoystickClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to by the [BallDropGame repository](https://github.com/tigoe/BallDropGame) 2 | -------------------------------------------------------------------------------- /NetworkExamples/BallDropWifiJoystickClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to by the [BallDropGame repository](https://github.com/tigoe/BallDropGame) 2 | -------------------------------------------------------------------------------- /NetworkExamples/BridgeCurlClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeJoystickClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeRestAccelerometer/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeRestParser/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeRestPut/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeRestRGB/readme.md: -------------------------------------------------------------------------------- 1 | This example has been superseded by the BridgeRestGet example in my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeSocket/readme.md: -------------------------------------------------------------------------------- 1 | This example has been superseded by the BridgeTCPSocket example in my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeTelnetClient/readme.md: -------------------------------------------------------------------------------- 1 | This example has been superseded by the BridgeTCPSocket and BridgeJoystick examples in my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeToDweet/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/BridgeToNode/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [Bridge Examples repository](https://github.com/tigoe/BridgeExamples) -------------------------------------------------------------------------------- /NetworkExamples/ExpressBasics/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 26 | 27 | 28 | 29 | 30 |
31 | What's your name: 32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /NetworkExamples/ExpressBasics/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | app = express(), 3 | clientName; 4 | 5 | app.configure(function () { 6 | /* 7 | use a directory called js in your project directory 8 | to serve static files. This is so you can serve client-side 9 | javaScript files with your index page. 10 | 11 | If you want to serve CSS, and/or lots of HTML files, it's 12 | useful to set up a static directory for them. express.js 13 | will then serve files from those directories like a regular 14 | webserver. 15 | */ 16 | app.use('/js', express.static(__dirname + '/js')); 17 | 18 | // start listening on port 8080: 19 | app.listen(8080, function () { 20 | console.log("Express configured. Listening on port 8080"); 21 | }); 22 | }); 23 | 24 | 25 | // respond to web GET requests with the index.html page. 26 | // this is how you serve a file that's not in a static directory: 27 | app.get('/', function (request, response) { 28 | response.sendfile('index.html'); 29 | console.log(request.ip); 30 | }); 31 | 32 | // function for serving index.html, or index. anything: 33 | app.get('/index*', function (request, response) { 34 | response.sendfile('index.html'); 35 | }); 36 | 37 | // function for serving index.html, or index. anything: 38 | app.get('/me', function (request, response) { 39 | //send a response to the client: 40 | response.writeHead(200, {'Content-Type': 'text/html'}); 41 | response.write("Your IP address: " + request.ip); 42 | response.end("\n\n"); 43 | }); 44 | 45 | // if the request is for /name/Joe, or /name/Jane, then express.js 46 | // will treat the second element of the address string as the name: 47 | app.get('/name/:name', function (request, response) { 48 | clientName = request.params.name; 49 | 50 | //send a response to the client: 51 | response.writeHead(200, {'Content-Type': 'text/html'}); 52 | response.write("You sent me the name: " + clientName); 53 | response.end(); 54 | }); 55 | 56 | // if the request is for /name without a value, return the current 57 | // value of clientName. If there is no value for clientName, 58 | // return a message to that effect: 59 | app.get('/name', function (request, response) { 60 | var content; 61 | 62 | if (!clientName) { 63 | content = "You didn't give me a name yet."; 64 | } else { 65 | content = clientName; 66 | } 67 | 68 | //send a response to the client: 69 | response.writeHead(200, {'Content-Type': 'text/html'}); 70 | response.write(content); 71 | response.end(); 72 | }); 73 | -------------------------------------------------------------------------------- /NetworkExamples/ExpressBasics/js/zepto.min.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ 2 | (function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) -------------------------------------------------------------------------------- /NetworkExamples/ExpressBasics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ExpressBasics", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "express": "3.x" 6 | }, 7 | "engines": { 8 | "node": "0.10.x", 9 | "npm": "1.3.x" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetworkExamples/ExpressBasics/readme.md: -------------------------------------------------------------------------------- 1 | This example shows how to use node.js and expres.js to exchange data between client and server in a RESTful way. 2 | 3 | To install this project, download all the components in one directory, then run npm install. 4 | 5 | The index.html page has one user-editable field, for a username. There are two buttons, one for getting the username from the server, and another for submitting the username to the server. 6 | 7 | The index.js server has four response functions, expecting HTTP GET or POST requests: 8 | 9 | GET / serves the index.html page 10 | 11 | GET /index* serves the index.html page for any request that starts with "index" 12 | 13 | GET /name sends the client the current value that the server has for a variable called clientName 14 | 15 | POST /name/:name sets clientName with the value of :name. 16 | 17 | The index.html uses zepto.js (a lightweight version of jQuery) to make requests to the server. Because the index.html page needs to load zepto.js, the server defines a directory called /js to serve static files. Without that, the index page won't be able to load zepto.js, or any other files. 18 | 19 | The index.html page works in an AJAXy way. Rather than having a form that submits everything at once, it makes requests using zepto.js. It has a text input field called username, and two buttons, one to submit the username and the other to get the user name from the server. The server replies with short strings of text that the client then fills into the text input field. -------------------------------------------------------------------------------- /NetworkExamples/JSClientThermostat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Thermostat

9 | Current Temperature: 10 | 15°C 11 |
12 | Desired Temperature: 13 | 15°C 14 |
15 | System Status: off 16 | 17 | -------------------------------------------------------------------------------- /NetworkExamples/JSClientThermostat/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #2e3f88; 3 | color: #ededed; 4 | font-family: "Helvetica", sans-serif; 5 | font-weight: lighter; 6 | letter-spacing: 1.5px; 7 | } 8 | 9 | #temperature { 10 | width:130px; 11 | } -------------------------------------------------------------------------------- /NetworkExamples/JSClientThermostat/thermostat.js: -------------------------------------------------------------------------------- 1 | var threshold = 2.0; // threshold for temperature change, in degrees C 2 | 3 | function setup() { 4 | // setup will be called when the HTML page body loads 5 | 6 | // add event listeners for all inputs: 7 | setPoint.addEventListener('change', updateDisplay, false); 8 | // set an interval timer to start the temperature change: 9 | setInterval(changeTemperature, 2000); 10 | } 11 | 12 | function updateDisplay() { 13 | // update the labels from the input and output values 14 | setPointLabel.innerHTML = setPoint.value; 15 | tempLabel.innerHTML = temperature.value; 16 | // change the temperature optimal range based on the setPoint: 17 | temperature.optimum = setPoint.value; 18 | temperature.high = temperature.optimum + threshold; 19 | temperature.low = temperature.optimum - threshold; 20 | 21 | // update the system status based on the temperature optimum: 22 | if (temperature.value >= temperature.high) { 23 | // system should be cooling 24 | statusLabel.innerHTML = "cooling"; 25 | } else if (temperature.value <= temperature.low) { 26 | // system should be heating 27 | statusLabel.innerHTML = "heating"; 28 | } else { 29 | // system should be off 30 | statusLabel.innerHTML = "off"; 31 | } 32 | } 33 | 34 | function changeTemperature() { 35 | // temperature changes based on system status and outside conditions 36 | switch (statusLabel.innerHTML) { 37 | case 'cooling': // temperature should be going down 38 | temperature.value -= Math.random(); // subtract a number between 0 and 1 39 | break; 40 | case 'heating': // temperature should be going up 41 | temperature.value += Math.random(); // add a number between 0 and 1 42 | break; 43 | case 'off': // temperature could go either way 44 | temperature.value += 2*Math.random() - 1; // add a number between -1 and 1 45 | break; 46 | } 47 | // update the display when the temperature changes: 48 | updateDisplay(); 49 | } -------------------------------------------------------------------------------- /NetworkExamples/JSClock/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 |
What time is it?
23 | 24 | -------------------------------------------------------------------------------- /NetworkExamples/README.md: -------------------------------------------------------------------------------- 1 | Network Examples 2 | 3 | This is a collection of networking scripts and programs for various purposes, and in various languages. It's all stuff that's not in my Making Things Talk 2 repo. 4 | 5 | Other than that, there's no overall structure to this repo. It's just stuff I've made to illustrate certain tasks, or to try out certain networking technologies. 6 | 7 | Enjoy. 8 | 9 | -Tom Igoe -------------------------------------------------------------------------------- /NetworkExamples/nodeImap/accounts.js: -------------------------------------------------------------------------------- 1 | /* 2 | This module contains the data for all your accounts, in the format 3 | that Imap expects it. 4 | */ 5 | var exports = module.exports = {}; 6 | 7 | exports.accounts = [ 8 | { 9 | user: 'tom.igoe@gmail.com', 10 | password: '', 11 | host:'imap.gmail.com', 12 | port: 993, 13 | tls: true 14 | }, 15 | { 16 | user: 'ti8@nyu.edu', 17 | password: '', 18 | host:'imap.gmail.com', 19 | port: 993, 20 | tls: true 21 | }, 22 | { 23 | user: 't.igoe@arduino.cc', 24 | password: '', 25 | host:'imap.gmail.com', 26 | port: 993, 27 | tls: true 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /NetworkExamples/nodeImap/index.js: -------------------------------------------------------------------------------- 1 | var Imap = require('imap'); 2 | var my = require('./accounts.js'); 3 | var totalCount = 0; 4 | 5 | for (a in my.accounts) { 6 | var thisAccount = new Imap(my.accounts[a]); 7 | checkMail(thisAccount); 8 | } 9 | 10 | 11 | function checkMail(imap) { 12 | function openInbox(callback) { 13 | imap.openBox('INBOX', true, callback); 14 | } 15 | 16 | imap.once('ready', function() { 17 | openInbox(readMailbox); 18 | }); 19 | 20 | function readMailbox(err, box) { 21 | if (err) throw err; 22 | 23 | var fetcher = imap.seq.fetch("1:" + box.messages.total, { 24 | bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)', 25 | struct: false, 26 | size: true 27 | }); 28 | 29 | fetcher.on('message', function(msg, seqno) { 30 | msg.once('attributes', function(attrs) { 31 | totalCount += attrs.size; 32 | }); 33 | }); 34 | 35 | fetcher.on('error', function(err) { 36 | console.log('Fetch error: ' + err); 37 | }); 38 | 39 | fetcher.on('end', function() { 40 | console.log("total mailbox size: " + totalCount); 41 | console.log('Done fetching all messages!'); 42 | imap.closeBox(box); 43 | 44 | //TO DO: Error seems to be that I am not closing the mailbox before 45 | // ending the connection 46 | imap.end(); 47 | }); 48 | } 49 | 50 | imap.on('error', function(err) { 51 | console.log(err); 52 | }); 53 | 54 | imap.on('end', function() { 55 | console.log('Connection ended'); 56 | }); 57 | 58 | imap.connect(); 59 | } 60 | -------------------------------------------------------------------------------- /NetworkExamples/nodeOpenWindow/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [NodeExamples repository](https://github.com/tigoe/NodeExamples) -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/README.md: -------------------------------------------------------------------------------- 1 | restToSerial.js 2 | 3 | This example allows you to send messages to an Arduino microcontroller 4 | from a web page using a RESTian communications scheme. The server application 5 | is written in node.js using the express.js web framework and node-serialport 6 | for serial communications. 7 | 8 | 9 | To use this, you should read up on node.js 10 | 11 | To install it: 12 | * make sure you've installed node.js 13 | * either clone the project in git or download it 14 | * from the command line,change directories to the directory where you downloaded the project 15 | 16 | Enter the following: 17 | 18 | npm install 19 | 20 | You should end up with a new directory called node_modules, which will include socket.io, node-serialport, and express.js. 21 | 22 | To run it, enter: 23 | 24 | node restToSerial.js portname 25 | 26 | Where portname is the name of your serial port. 27 | -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/RGBLEDControl/RGBLEDControl.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Serial RGB LED controller 3 | Context: Arduino 4 | 5 | Controls an RGB LED whose R, G and B legs are 6 | connected to pins 9, 11, and 10, respectively. 7 | This is for a common cathode RGB LED. 8 | The cathode is attached to ground. 9 | 10 | To control it, send a string formatted like so: 11 | r/255/g/0/b/127 12 | or r255g0b127 13 | 14 | This was designed to be used with a REST or 15 | OSC-formatted command string, as shown above. 16 | 17 | created 19 July 2010 18 | modified 7 Jul 2014 19 | by Tom Igoe 20 | 21 | */ 22 | 23 | // constants to hold the output pin numbers: 24 | const int greenPin = 9; 25 | const int bluePin = 10; 26 | const int redPin = 11; 27 | 28 | void setup() { 29 | // initiate serial communication: 30 | Serial.begin(9600); 31 | Serial.setTimeout(10); 32 | // initialize the LED pins as outputs: 33 | pinMode(redPin, OUTPUT); 34 | pinMode(greenPin, OUTPUT); 35 | pinMode(bluePin, OUTPUT); 36 | pinMode(8, OUTPUT); 37 | digitalWrite(8, LOW); 38 | // set the color pins high to turn off the LED: 39 | digitalWrite(redPin, LOW); 40 | digitalWrite(greenPin, LOW); 41 | digitalWrite(bluePin, LOW); 42 | 43 | } 44 | void loop() { 45 | 46 | int currentPin = 0; // current pin to be faded 47 | 48 | // if there's any serial data in the buffer, read a byte: 49 | if (Serial.available() > 0) { 50 | int inByte = Serial.read(); 51 | 52 | // respond to the values 'r', 'g', 'b'. 53 | // you don't care about any other value: 54 | switch (inByte) { 55 | case'r': // red 56 | currentPin = redPin; 57 | break; 58 | case 'g': // green 59 | currentPin = greenPin; 60 | 61 | break; 62 | case 'b': // blue 63 | currentPin = bluePin; 64 | break; 65 | } 66 | 67 | // if you have a legitimate pin number, 68 | // use the parseInt function to listen for a level: 69 | if (currentPin != 0) { 70 | int brightness = Serial.parseInt(); 71 | // map the result to a level from 0 to 255 72 | brightness = map(brightness, 0, 100, 0, 255); 73 | 74 | // set the brightness for this color: 75 | analogWrite(currentPin, brightness); 76 | Serial.println(brightness); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | restToSerial 3 | a node.js app to read take requests and send as serial data 4 | requires: 5 | * node.js (http://nodejs.org/) 6 | * servi.js (https://github.com/antiboredom/servi.js) 7 | * serialport.js (https://github.com/voodootikigod/node-serialport) 8 | 9 | To launch this, type 'node index.js portname' on the commandline, where 10 | portname is the name of your serial port. 11 | 12 | created 5 Nov 2012 13 | modified 21 Oct 2014 14 | by Tom Igoe 15 | */ 16 | 17 | var serialport = require("serialport"), // include the serialport library 18 | SerialPort = serialport.SerialPort, // make a local instance of serial 19 | servi = require('servi'), // include the servi library 20 | app = new servi(false); // servi instance 21 | 22 | // configure the server's behavior: 23 | app.port(8080); // port number to run the server on 24 | app.serveFiles("public"); // serve all static HTML files from /public 25 | 26 | 27 | // respond to web GET requests for the index.html page: 28 | app.route('/', sendIndexPage); 29 | app.route('/index*', sendIndexPage); 30 | // take anything that begins with /output as an LED request: 31 | app.route('/output/:color/:brightness', sendToSerial); 32 | 33 | // now that everything is configured, start the server: 34 | app.start(); 35 | console.log("Listening for new clients on port 8080"); 36 | 37 | 38 | // the third word of the command line command is serial port name: 39 | var portName = process.argv[2]; 40 | // print out the port you're listening on: 41 | console.log("opening serial port: " + portName); 42 | 43 | // open the serial port. Uses the command line parameter: 44 | var myPort = new SerialPort(portName, { 45 | baudRate: 9600, 46 | // look for return and newline at the end of each data packet: 47 | parser: serialport.parsers.readline("\r\n") 48 | }); 49 | 50 | /* The rest of the functions are event-driven. 51 | They only get called when the server gets incoming GET requests: 52 | */ 53 | 54 | // this function responds to a GET request with the index page: 55 | function sendIndexPage(request) { 56 | request.serveFile('/index.html'); 57 | } 58 | 59 | function sendToSerial(request) { 60 | // get the parameters from the URL: 61 | var brightnessCommand = request.params.color + request.params.brightness; 62 | console.log("received "+ brightnessCommand); 63 | 64 | // send it out the serial port: 65 | myPort.write(brightnessCommand); 66 | // send the data and close the connection: 67 | request.respond(brightnessCommand); 68 | } -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'install' ] 3 | 2 info using npm@1.4.28 4 | 3 info using node@v0.10.32 5 | 4 warn package.json restToSerial@0.5.0 No repository field. 6 | 5 verbose readDependencies using package.json deps 7 | 6 verbose install where, deps [ '/Users/tigoe/Documents/github/NetworkExamples/nodeRestToSerial', 8 | 6 verbose install [ 'serialport', 'servi' ] ] 9 | 7 info preinstall restToSerial@0.5.0 10 | 8 verbose readDependencies using package.json deps 11 | 9 verbose cache add [ 'serialport@1.4.x', null ] 12 | 10 verbose cache add name=undefined spec="serialport@1.4.x" args=["serialport@1.4.x",null] 13 | 11 verbose parsed url { protocol: null, 14 | 11 verbose parsed url slashes: null, 15 | 11 verbose parsed url auth: null, 16 | 11 verbose parsed url host: null, 17 | 11 verbose parsed url port: null, 18 | 11 verbose parsed url hostname: null, 19 | 11 verbose parsed url hash: null, 20 | 11 verbose parsed url search: null, 21 | 11 verbose parsed url query: null, 22 | 11 verbose parsed url pathname: 'serialport@1.4.x', 23 | 11 verbose parsed url path: 'serialport@1.4.x', 24 | 11 verbose parsed url href: 'serialport@1.4.x' } 25 | 12 verbose cache add [ 'servi@>=0.5.0', null ] 26 | 13 verbose cache add name=undefined spec="servi@>=0.5.0" args=["servi@>=0.5.0",null] 27 | 14 verbose parsed url { protocol: null, 28 | 14 verbose parsed url slashes: null, 29 | 14 verbose parsed url auth: null, 30 | 14 verbose parsed url host: null, 31 | 14 verbose parsed url port: null, 32 | 14 verbose parsed url hostname: null, 33 | 14 verbose parsed url hash: null, 34 | 14 verbose parsed url search: null, 35 | 14 verbose parsed url query: null, 36 | 14 verbose parsed url pathname: 'servi@%3E=0.5.0', 37 | 14 verbose parsed url path: 'servi@%3E=0.5.0', 38 | 14 verbose parsed url href: 'servi@%3E=0.5.0' } 39 | 15 verbose cache add name="serialport" spec="1.4.x" args=["serialport","1.4.x"] 40 | 16 verbose parsed url { protocol: null, 41 | 16 verbose parsed url slashes: null, 42 | 16 verbose parsed url auth: null, 43 | 16 verbose parsed url host: null, 44 | 16 verbose parsed url port: null, 45 | 16 verbose parsed url hostname: null, 46 | 16 verbose parsed url hash: null, 47 | 16 verbose parsed url search: null, 48 | 16 verbose parsed url query: null, 49 | 16 verbose parsed url pathname: '1.4.x', 50 | 16 verbose parsed url path: '1.4.x', 51 | 16 verbose parsed url href: '1.4.x' } 52 | 17 verbose addNamed [ 'serialport', '1.4.x' ] 53 | 18 verbose addNamed [ null, '>=1.4.0-0 <1.5.0-0' ] 54 | 19 verbose cache add name="servi" spec=">=0.5.0" args=["servi",">=0.5.0"] 55 | 20 verbose parsed url { protocol: null, 56 | 20 verbose parsed url slashes: null, 57 | 20 verbose parsed url auth: null, 58 | 20 verbose parsed url host: null, 59 | 20 verbose parsed url port: null, 60 | 20 verbose parsed url hostname: null, 61 | 20 verbose parsed url hash: null, 62 | 20 verbose parsed url search: null, 63 | 20 verbose parsed url query: null, 64 | 20 verbose parsed url pathname: '%3E=0.5.0', 65 | 20 verbose parsed url path: '%3E=0.5.0', 66 | 20 verbose parsed url href: '%3E=0.5.0' } 67 | 21 verbose addNamed [ 'servi', '>=0.5.0' ] 68 | 22 verbose addNamed [ null, '>=0.5.0' ] 69 | 23 silly lockFile ab1a05c6-serialport-1-4-x serialport@1.4.x 70 | 24 verbose lock serialport@1.4.x /Users/tigoe/.npm/ab1a05c6-serialport-1-4-x.lock 71 | 25 silly lockFile 4cc48d69-servi-0-5-0 servi@>=0.5.0 72 | 26 verbose lock servi@>=0.5.0 /Users/tigoe/.npm/4cc48d69-servi-0-5-0.lock 73 | 27 silly addNameRange { name: 'serialport', 74 | 27 silly addNameRange range: '>=1.4.0-0 <1.5.0-0', 75 | 27 silly addNameRange hasData: false } 76 | 28 silly addNameRange { name: 'servi', range: '>=0.5.0', hasData: false } 77 | 29 verbose request where is /serialport 78 | 30 verbose request registry https://registry.npmjs.org/ 79 | 31 verbose request id 854ba5622d04a949 80 | 32 verbose url raw /serialport 81 | 33 verbose url resolving [ 'https://registry.npmjs.org/', './serialport' ] 82 | 34 verbose url resolved https://registry.npmjs.org/serialport 83 | 35 verbose request where is https://registry.npmjs.org/serialport 84 | 36 info trying registry request attempt 1 at 13:16:41 85 | 37 verbose etag "6GZS28CQYYAS6ICODDMR7LLF8" 86 | 38 http GET https://registry.npmjs.org/serialport 87 | 39 verbose request where is /servi 88 | 40 verbose request registry https://registry.npmjs.org/ 89 | 41 verbose url raw /servi 90 | 42 verbose url resolving [ 'https://registry.npmjs.org/', './servi' ] 91 | 43 verbose url resolved https://registry.npmjs.org/servi 92 | 44 verbose request where is https://registry.npmjs.org/servi 93 | 45 info trying registry request attempt 1 at 13:16:41 94 | 46 verbose etag "BF26W2F1EAW9DEDUX9EXS4UI8" 95 | 47 http GET https://registry.npmjs.org/servi 96 | 48 http 304 https://registry.npmjs.org/servi 97 | 49 silly registry.get cb [ 304, 98 | 49 silly registry.get { date: 'Tue, 21 Oct 2014 17:16:41 GMT', 99 | 49 silly registry.get server: 'Apache', 100 | 49 silly registry.get via: '1.1 varnish', 101 | 49 silly registry.get 'last-modified': 'Tue, 21 Oct 2014 17:16:41 GMT', 102 | 49 silly registry.get 'cache-control': 'max-age=60', 103 | 49 silly registry.get etag: '"BF26W2F1EAW9DEDUX9EXS4UI8"', 104 | 49 silly registry.get age: '32', 105 | 49 silly registry.get 'x-served-by': 'cache-iad2133-IAD', 106 | 49 silly registry.get 'x-cache': 'HIT', 107 | 49 silly registry.get 'x-cache-hits': '1', 108 | 49 silly registry.get 'x-timer': 'S1413911801.735100,VS0,VE0', 109 | 49 silly registry.get vary: 'Accept', 110 | 49 silly registry.get 'content-length': '0', 111 | 49 silly registry.get 'keep-alive': 'timeout=10, max=50', 112 | 49 silly registry.get connection: 'Keep-Alive' } ] 113 | 50 verbose etag https://registry.npmjs.org/servi from cache 114 | 51 http 304 https://registry.npmjs.org/serialport 115 | 52 silly registry.get cb [ 304, 116 | 52 silly registry.get { date: 'Tue, 21 Oct 2014 17:16:41 GMT', 117 | 52 silly registry.get server: 'Apache', 118 | 52 silly registry.get via: '1.1 varnish', 119 | 52 silly registry.get 'last-modified': 'Tue, 21 Oct 2014 17:16:41 GMT', 120 | 52 silly registry.get 'cache-control': 'max-age=60', 121 | 52 silly registry.get etag: '"6GZS28CQYYAS6ICODDMR7LLF8"', 122 | 52 silly registry.get age: '32', 123 | 52 silly registry.get 'x-served-by': 'cache-iad2128-IAD', 124 | 52 silly registry.get 'x-cache': 'HIT', 125 | 52 silly registry.get 'x-cache-hits': '1', 126 | 52 silly registry.get 'x-timer': 'S1413911801.744523,VS0,VE0', 127 | 52 silly registry.get vary: 'Accept', 128 | 52 silly registry.get 'content-length': '0', 129 | 52 silly registry.get 'keep-alive': 'timeout=10, max=50', 130 | 52 silly registry.get connection: 'Keep-Alive' } ] 131 | 53 verbose etag https://registry.npmjs.org/serialport from cache 132 | 54 silly addNameRange number 2 { name: 'serialport', 133 | 54 silly addNameRange range: '>=1.4.0-0 <1.5.0-0', 134 | 54 silly addNameRange hasData: true } 135 | 55 silly addNameRange versions [ 'serialport', 136 | 55 silly addNameRange [ '0.1.0', 137 | 55 silly addNameRange '0.1.1', 138 | 55 silly addNameRange '0.1.3', 139 | 55 silly addNameRange '0.2.0', 140 | 55 silly addNameRange '0.2.2', 141 | 55 silly addNameRange '0.2.3', 142 | 55 silly addNameRange '0.2.4', 143 | 55 silly addNameRange '0.2.5', 144 | 55 silly addNameRange '0.2.6', 145 | 55 silly addNameRange '0.2.7', 146 | 55 silly addNameRange '0.2.8', 147 | 55 silly addNameRange '0.2.9', 148 | 55 silly addNameRange '0.3.0', 149 | 55 silly addNameRange '0.6.0', 150 | 55 silly addNameRange '0.6.1', 151 | 55 silly addNameRange '0.6.2', 152 | 55 silly addNameRange '0.6.3', 153 | 55 silly addNameRange '0.6.5', 154 | 55 silly addNameRange '0.6.6', 155 | 55 silly addNameRange '0.6.7', 156 | 55 silly addNameRange '0.7.0', 157 | 55 silly addNameRange '0.7.1', 158 | 55 silly addNameRange '0.7.2', 159 | 55 silly addNameRange '0.7.3', 160 | 55 silly addNameRange '0.7.4', 161 | 55 silly addNameRange '0.7.5', 162 | 55 silly addNameRange '1.0.0', 163 | 55 silly addNameRange '1.0.1', 164 | 55 silly addNameRange '1.0.2', 165 | 55 silly addNameRange '1.0.3', 166 | 55 silly addNameRange '1.0.4', 167 | 55 silly addNameRange '1.0.5', 168 | 55 silly addNameRange '1.0.6', 169 | 55 silly addNameRange '1.0.7', 170 | 55 silly addNameRange '1.0.8', 171 | 55 silly addNameRange '1.1.0', 172 | 55 silly addNameRange '1.1.1', 173 | 55 silly addNameRange '1.1.3', 174 | 55 silly addNameRange '1.2.0', 175 | 55 silly addNameRange '1.2.1', 176 | 55 silly addNameRange '1.2.2', 177 | 55 silly addNameRange '1.2.3', 178 | 55 silly addNameRange '1.2.4', 179 | 55 silly addNameRange '1.2.5', 180 | 55 silly addNameRange '1.3.0', 181 | 55 silly addNameRange '1.3.1', 182 | 55 silly addNameRange '1.4.0', 183 | 55 silly addNameRange '1.4.1', 184 | 55 silly addNameRange '1.4.2', 185 | 55 silly addNameRange '1.4.5', 186 | 55 silly addNameRange '1.4.6' ] ] 187 | 56 verbose addNamed [ 'serialport', '1.4.6' ] 188 | 57 verbose addNamed [ '1.4.6', '1.4.6' ] 189 | 58 silly lockFile 12e7db8b-serialport-1-4-6 serialport@1.4.6 190 | 59 verbose lock serialport@1.4.6 /Users/tigoe/.npm/12e7db8b-serialport-1-4-6.lock 191 | 60 silly addNameRange number 2 { name: 'servi', range: '>=0.5.0', hasData: true } 192 | 61 silly addNameRange versions [ 'servi', 193 | 61 silly addNameRange [ '0.0.1', 194 | 61 silly addNameRange '0.0.2-alpha', 195 | 61 silly addNameRange '0.0.3', 196 | 61 silly addNameRange '0.0.4', 197 | 61 silly addNameRange '0.0.6', 198 | 61 silly addNameRange '0.0.7', 199 | 61 silly addNameRange '0.0.8' ] ] 200 | 62 silly lockFile 4cc48d69-servi-0-5-0 servi@>=0.5.0 201 | 63 silly lockFile 4cc48d69-servi-0-5-0 servi@>=0.5.0 202 | 64 silly lockFile 12e7db8b-serialport-1-4-6 serialport@1.4.6 203 | 65 silly lockFile 12e7db8b-serialport-1-4-6 serialport@1.4.6 204 | 66 silly lockFile ab1a05c6-serialport-1-4-x serialport@1.4.x 205 | 67 silly lockFile ab1a05c6-serialport-1-4-x serialport@1.4.x 206 | 68 error notarget No compatible version found: servi@'>=0.5.0' 207 | 68 error notarget Valid install targets: 208 | 68 error notarget ["0.0.1","0.0.2-alpha","0.0.3","0.0.4","0.0.6","0.0.7","0.0.8"] 209 | 68 error notarget 210 | 68 error notarget This is most likely not a problem with npm itself. 211 | 68 error notarget In most cases you or one of your dependencies are requesting 212 | 68 error notarget a package version that doesn't exist. 213 | 69 error System Darwin 13.4.0 214 | 70 error command "/usr/local/bin/node" "/usr/local/bin/npm" "install" 215 | 71 error cwd /Users/tigoe/Documents/github/NetworkExamples/nodeRestToSerial 216 | 72 error node -v v0.10.32 217 | 73 error npm -v 1.4.28 218 | 74 error code ETARGET 219 | 75 verbose exit [ 1, true ] 220 | -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "restToSerial", 3 | "version": "0.6.0", 4 | "author": { 5 | "name":"Tom Igoe" 6 | }, 7 | "dependencies": { 8 | "serialport": "1.4.x", 9 | "servi": ">=0.0.8" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetworkExamples/nodeRestToSerial/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 |
30 | 31 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialIntro/README.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [NodeExamples repository](https://github.com/tigoe/NodeExamples) -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/ADXL326/ADXL326.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ADXL326 3 | 4 | Reads an ADXL326 3-axis accelerometer from Adafruit. 5 | Sends the results as a JSON-formatted string like so: 6 | {"x":"345", "y":"432", "z":"234"} 7 | 8 | created 16 Oct 2012 9 | by Tom Igoe 10 | */ 11 | 12 | //Set up pins for Adafruit ADXL326 breakout board: 13 | const int Vin = A0; 14 | const int Gnd = A2; 15 | const int zPin = A3; 16 | const int yPin = A4; 17 | const int xPin = A5; 18 | 19 | boolean sending = false; 20 | 21 | void setup() { 22 | Serial.begin(9600); 23 | // initialize power and ground pins for accelerometer: 24 | pinMode(Vin, OUTPUT); 25 | pinMode(Gnd, OUTPUT); 26 | digitalWrite(Vin, HIGH); 27 | digitalWrite(Gnd, LOW); 28 | } 29 | 30 | void loop() { 31 | // read for incoming messages. c = send, x = don't send: 32 | char inChar = Serial.read(); 33 | switch (inChar) { 34 | case 'c': // connection open 35 | sending = true; 36 | break; 37 | case 'x': // connection closed 38 | sending = false; 39 | break; 40 | } 41 | 42 | if (sending) { 43 | // read sensors: 44 | int x = analogRead(xPin); 45 | delay(1); 46 | int y = analogRead(yPin); 47 | delay(1); 48 | int z = analogRead(zPin); 49 | 50 | // form a JSON-formatted string: 51 | String jsonString = "{\"x\":\""; 52 | jsonString += x; 53 | jsonString +="\",\"y\":\""; 54 | jsonString += y; 55 | jsonString +="\",\"z\":\""; 56 | jsonString += z; 57 | jsonString +="\"}"; 58 | 59 | // print it: 60 | Serial.println(jsonString); 61 | } 62 | } 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/Joystick/Joystick.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Joystick 3 | 4 | Reads a 2-axis joystick with pushbutton from Adafruit. 5 | Sends the results as a JSON-formatted string like so: 6 | {"x":"345", "y":"432", "z":"255"} 7 | 8 | created 16 Oct 2012 9 | modified 17 Jun 2014 10 | by Tom Igoe 11 | */ 12 | 13 | //Set up pins for Adafruit Joystick breakout board: 14 | const int Vin = A0; 15 | const int Gnd = A4; 16 | const int buttonPin = A3; 17 | const int yPin = A2; 18 | const int xPin = A1; 19 | 20 | boolean sending = false; 21 | 22 | void setup() { 23 | Serial.begin(9600); 24 | // initialize power and ground pins for joystick: 25 | pinMode(Vin, OUTPUT); 26 | pinMode(Gnd, OUTPUT); 27 | digitalWrite(Vin, HIGH); 28 | digitalWrite(Gnd, LOW); 29 | pinMode(buttonPin, INPUT_PULLUP); 30 | } 31 | 32 | void loop() { 33 | // read for incoming messages. c = send, x = don't send: 34 | char inChar = Serial.read(); 35 | switch (inChar) { 36 | case 'c': // connection open 37 | sending = true; 38 | break; 39 | case 'x': // connection closed 40 | sending = false; 41 | break; 42 | } 43 | 44 | if (sending) { 45 | // read sensors: 46 | int x = analogRead(xPin); 47 | delay(1); 48 | int y = analogRead(yPin); 49 | delay(1); 50 | int button = digitalRead(buttonPin); 51 | 52 | // form a JSON-formatted string: 53 | String jsonString = "{\"x\":\""; 54 | jsonString += x; 55 | jsonString +="\",\"y\":\""; 56 | jsonString += y; 57 | jsonString +="\",\"z\":\""; 58 | jsonString += button*255; 59 | jsonString +="\"}"; 60 | 61 | // print it: 62 | Serial.println(jsonString); 63 | } 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/README.md: -------------------------------------------------------------------------------- 1 | SerialToJSON.js 2 | 3 | A serial-to-web example using node.js, node-serialport, and socket.io. This example 4 | converts a serial string into a JSON object and sends that via webSocket 5 | 6 | To use this, you should read up on node.js 7 | 8 | To install it: 9 | * make sure you've installed node.js 10 | * either clone the project in git or download it 11 | * from the command line,change directories to the directory where you downloaded the project 12 | 13 | Enter the following: 14 | 15 | npm install 16 | 17 | You should end up with a new directory called node_modules, which will include socket.io, node-serialport, and express.js. 18 | 19 | To run it, enter: 20 | 21 | node SerialToJSON.js portname 22 | 23 | Where portname is the name of your serial port. 24 | 25 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 |
Hello

23 | 24 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | SerialToJson.js 3 | a node.js app to read serial strings, convert them to 4 | JSON objects, and send them to webSocket clients 5 | requires: 6 | * node.js (http://nodejs.org/) 7 | * express.js (http://expressjs.com/) 8 | * socket.io (http://socket.io/#how-to-use) 9 | * serialport.js (https://github.com/voodootikigod/node-serialport) 10 | 11 | To call it type: 12 | node SerialToJSON.js portname 13 | 14 | where portname is the path to the serial port you want to open. 15 | 16 | created 1 Nov 2012 17 | modified 7 Nov 2012 18 | by Tom Igoe 19 | 20 | */ 21 | 22 | var serialport = require("serialport"), // include the serialport library 23 | SerialPort = serialport.SerialPort, // make a local instance of serial 24 | app = require('express')(), // start Express framework 25 | server = require('http').createServer(app), // start an HTTP server 26 | io = require('socket.io').listen(server); // filter the server using socket.io 27 | 28 | var portName = process.argv[2]; // third word of the command line should be serial port name 29 | console.log("opening serial port: " + portName); // print out the port you're listening on 30 | 31 | server.listen(8080); // listen for incoming requests on the server 32 | console.log("Listening for new clients on port 8080"); 33 | var connected = false; 34 | 35 | // open the serial port. Change the name to the name of your port, just like in Processing and Arduino: 36 | var myPort = new SerialPort(portName, { 37 | // look for return and newline at the end of each data packet: 38 | parser: serialport.parsers.readline("\r\n") 39 | }); 40 | 41 | // respond to web GET requests with the index.html page: 42 | app.get('/', function (request, response) { 43 | response.sendfile(__dirname + '/index.html'); 44 | }); 45 | 46 | 47 | // listen for new socket.io connections: 48 | io.sockets.on('connection', function (socket) { 49 | // if the client connects: 50 | if (!connected) { 51 | // clear out any old data from the serial bufffer: 52 | myPort.flush(); 53 | // send a byte to the serial port to ask for data: 54 | myPort.write('c'); 55 | console.log('user connected'); 56 | connected = true; 57 | } 58 | 59 | // if the client disconnects: 60 | socket.on('disconnect', function () { 61 | myPort.write('x'); 62 | console.log('user disconnected'); 63 | connected = false; 64 | }); 65 | 66 | // listen for new serial data: 67 | myPort.on('data', function (data) { 68 | // Convert the string into a JSON object: 69 | var serialData = JSON.parse(data); 70 | // for debugging, you should see this in the terminal window: 71 | console.log(data); 72 | // send a serial event to the web client with the data: 73 | socket.emit('serialEvent', serialData); 74 | }); 75 | }); 76 | 77 | 78 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToJSON/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodeSerialToJSON", 3 | "version": "0.2.2", 4 | "description" : "simple serial-to-broswer server application", 5 | "keywords": "serial, socket.io, node-serialport", 6 | "author": { 7 | "name":"Tom Igoe" 8 | }, 9 | "dependencies": { 10 | "serialport": "1.4.x", 11 | "socket.io": "0.9.x", 12 | "express": "3.x" 13 | }, 14 | "engines": { 15 | "node": "0.10.x", 16 | "npm": "1.3.x" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToRest/ArduinoSerialParse/ArduinoSerialParse.ino: -------------------------------------------------------------------------------- 1 | void setup() { 2 | // initialize serial communication: 3 | Serial.begin(9600); 4 | // set the serial receive timeout to 10ms: 5 | Serial.setTimeout(10); 6 | } 7 | 8 | void loop() { 9 | // when there's serial data: 10 | while (Serial.available()) { 11 | // parse incoming data for a number: 12 | int channel = Serial.parseInt(); 13 | // if the number's between 0 and 6: 14 | if (channel >= 0 && channel < 6 ) { 15 | // read the corresponding analog input: 16 | int sensor = analogRead(channel); 17 | // print the result back to the server: 18 | Serial.println(sensor); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToRest/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | serialToRest 3 | a node.js app to read take requests and reply with serial data 4 | requires: 5 | * node.js (http://nodejs.org/) 6 | * servi.js (https://github.com/antiboredom/servi.js) 7 | * serialport.js (https://github.com/voodootikigod/node-serialport) 8 | 9 | 10 | created 5 Nov 2012 11 | modified 21 Oct 2014 12 | by Tom Igoe 13 | 14 | */ 15 | 16 | var serialport = require("serialport"), // include the serialport library 17 | SerialPort = serialport.SerialPort, // make a local instance of serial 18 | servi = require('servi'), // include the servi library 19 | app = new servi(false); // servi instance 20 | 21 | // configure the server's behavior: 22 | app.port(8080); // port number to run the server on 23 | app.serveFiles("public"); // serve all static HTML files from /public 24 | // respond to calls for the index page: 25 | app.route('/', sendIndexPage); 26 | // take anything that begins with /output: 27 | app.route('/analog/:channel', getAnalogReading); 28 | 29 | // now that everything is configured, start the server: 30 | app.start(); 31 | console.log("Listening for new clients on port 8080"); 32 | 33 | // the third word of the command line command is serial port name: 34 | var portName = process.argv[2]; 35 | // print out the port you're listening on: 36 | console.log("opening serial port: " + portName); 37 | 38 | // open the serial port. Uses the command line parameter: 39 | var myPort = new SerialPort(portName, { 40 | baudRate: 9600, 41 | // look for return and newline at the end of each data packet: 42 | parser: serialport.parsers.readline("\r\n") 43 | }); 44 | 45 | 46 | /* The rest of the functions are event-driven. 47 | They only get called when the server gets incoming GET requests: 48 | */ 49 | 50 | // this function responds to a GET request with the index page: 51 | function sendIndexPage(request) { 52 | request.serveFile('/index.html'); 53 | } 54 | 55 | // get an analog reading from the serial port: 56 | function getAnalogReading(request) { 57 | // the parameter after /analog/ is the channel number: 58 | var channel = request.params.channel; 59 | console.log("getting channel: "+ channel + "..."); 60 | 61 | // send it out the serial port and wait for a response: 62 | myPort.write(channel, function() { 63 | // when you get a response from the serial port, write it out to the client: 64 | myPort.on('data', function(data) { 65 | // send the data and close the connection: 66 | request.respond(data); 67 | }); 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToRest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serialToRest", 3 | "version": "0.0.2", 4 | "description" : "A serial-to-browser application using RESTful URL calls", 5 | "keywords": "serial, node-serialport", 6 | "author": { 7 | "name":"Tom Igoe" 8 | }, 9 | "dependencies": { 10 | "serialport": "1.3.x", 11 | "servi": ">=0.0.8", 12 | "open": ">=0.0.4" 13 | }, 14 | "engines": { 15 | "node": "0.10.x", 16 | "npm": "1.3.x" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSerialToRest/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 41 | 42 | 43 | Enter an analog channel number to read: 44 | 45 |
46 | 47 | 48 | -------------------------------------------------------------------------------- /NetworkExamples/nodeSimpleServer/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [NodeExamples repository](https://github.com/tigoe/NodeExamples) -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/css/style.css: -------------------------------------------------------------------------------- 1 | #controls: { 2 | 3 | } 4 | 5 | html, 6 | body { 7 | background: #1b5c8c; 8 | color: #ededed; 9 | font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; 10 | font-weight: light; 11 | line-height: 1.5; 12 | letter-spacing: 0.7px; 13 | -webkit-font-smoothing: antialiased; 14 | } -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | Desired temperature: 11 | 12 |
13 | 14 | Current temperature: 15 | 16 | 17 |
18 | 19 | System status: 20 |
21 | 22 | -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | thermostat 3 | a node.js app to communicate between a serial thermostat device 4 | and a web client version of the same. 5 | requires: 6 | * node.js (http://nodejs.org/) 7 | * express.js (http://expressjs.com/) 8 | * socket.io (http://socket.io/#how-to-use) 9 | * serialport.js (https://github.com/voodootikigod/node-serialport) 10 | 11 | based on the core examples for socket.io and serialport.js 12 | 13 | created 21 Jan 2014 14 | by Tom Igoe 15 | 16 | */ 17 | 18 | 19 | 20 | 21 | 22 | var serialport = require("serialport"), // include the serialport library 23 | SerialPort = serialport.SerialPort, // make a local instance of serial 24 | express = require('express'), // make an instance of express 25 | open = require('open'), // used to open the browser 26 | url = 'http://localhost:8080'; // URL to open in the browser 27 | 28 | var app = express(), // start Express framework 29 | server = require('http').createServer(app); // start an HTTP server 30 | io = require('socket.io').listen(server); // listen for websocket requests 31 | 32 | 33 | // set up static folders for client-side JavaScript and CSS: 34 | app.use('/js', express.static(__dirname + '/js')); 35 | app.use('/css', express.static(__dirname + '/css')); 36 | 37 | var thermostat = { 38 | "temp": "0.0", 39 | "setPoint": "0.0" 40 | } 41 | 42 | // third word of the command line is serial port name: 43 | var portName = process.argv[2]; 44 | // print out the port you're listening on: 45 | console.log("opening serial port: " + portName); 46 | 47 | // listen for incoming requests on the server: 48 | server.listen(8080); 49 | console.log("Listening for new clients on port 8080"); 50 | // open the app in a browser: 51 | open(url); 52 | 53 | // open the serial port: 54 | var myPort = new SerialPort(portName, { 55 | // look for return and newline at the end of each data packet: 56 | parser: serialport.parsers.readline("\r\n") 57 | }); 58 | 59 | // respond to web GET requests with the index.html page: 60 | app.get('/', function (request, response) { 61 | response.sendfile(__dirname + '/index.html'); 62 | }); 63 | 64 | 65 | // listen for new socket.io connections: 66 | io.sockets.on('connection', function (socket) { 67 | // if there's a socket client, listen for new serial data: 68 | myPort.on('data', function (data) { 69 | // split the incoming data values on the comma: 70 | var values = data.split(','); 71 | // you now have two values in the array: 72 | // temp, followed by setPoint: 73 | thermostat.setPoint = parseFloat(values[0]); 74 | thermostat.temp = parseFloat(values[1]); 75 | 76 | // send a serial event to the web client with the data: 77 | socket.emit('serialEvent', thermostat); 78 | }); 79 | 80 | // if you get incoming data from the client, it'll be 81 | // the updated setPoint. Send it out the serial port: 82 | socket.on('socketEvent', function (data) { 83 | myPort.write(data.setPoint + '\n'); 84 | }); 85 | }); 86 | 87 | 88 | -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/js/thermostat.js: -------------------------------------------------------------------------------- 1 | 2 | var threshold = 2.0; // temperature change threshold, in deg. C 3 | 4 | // when page is ready, run this to bind UI listeners, etc. 5 | function bindEvents() { 6 | // bind this function to the setPoint slider's change: 7 | setPoint.addEventListener('change', updateSetPoint, false); 8 | updateDisplay(); 9 | } 10 | 11 | 12 | // open a connection to the serial server: 13 | var socket = io.connect('http://localhost:8080'); 14 | 15 | // when you get a serialdata event, do this: 16 | socket.on('serialEvent', function (data) { 17 | // set the stuff inside the element's HTML tags to 18 | // whatever the 'value' property of the received data is: 19 | temperature.value = data.temp; 20 | setPoint.value = data.setPoint; 21 | updateDisplay(); 22 | }); 23 | 24 | 25 | var updateSetPoint = function() { 26 | updateDisplay(); 27 | socket.emit('socketEvent', { "setPoint" : setPoint.value }); 28 | }; 29 | 30 | 31 | function updateDisplay() { 32 | setPointVal.innerHTML = setPoint.value + '°C'; 33 | temperature.high = setPoint.value + threshold; 34 | temperature.low = setPoint.value - threshold; 35 | temperature.optimum = setPoint.value; 36 | 37 | // update the temperature text label: 38 | tempVal.innerHTML = temperature.value + '°C'; 39 | 40 | // depending on the new temperature, 41 | // change the state of the system. 42 | // if the difference is past the threshold: 43 | if (Math.abs(temperature.value - setPoint.value) > threshold) { 44 | // if temp > setPoint, cool off: 45 | if (temperature.value > setPoint.value) { 46 | state.innerHTML = 'cooling'; 47 | } else { 48 | // if temp < setPoint, heat up: 49 | state.innerHTML = 'warming'; 50 | } 51 | // if within threshold, turn system off: 52 | } else { 53 | state.innerHTML = 'off'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodeThermostat", 3 | "version": "0.0.1", 4 | "description" : "demonstrates CSV to browser", 5 | "keywords": "serial, socket.io, node-serialport", 6 | "author": { 7 | "name":"Tom Igoe" 8 | }, 9 | "dependencies": { 10 | "serialport": "1.1.x", 11 | "socket.io": "0.9.x", 12 | "express": "3.x", 13 | "open": ">=0.0.4" 14 | }, 15 | "engines": { 16 | "node": "0.10.x", 17 | "npm": "1.3.x" 18 | } 19 | } -------------------------------------------------------------------------------- /NetworkExamples/nodeThermostat/thermostat/thermostat.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float previousTemp = 0.0; // the last temperature reading 4 | float setPoint = 10.0; // the current setPoint 5 | float prevSetPoint = 10.0; // the last setPoint reading 6 | int prevEncoderPos = -1; // the last encoder reading 7 | 8 | Encoder encoder(2, 3); // initialize encoder on pins 2 and 3 9 | 10 | void setup() { 11 | pinMode (A1, OUTPUT); 12 | pinMode(A3, OUTPUT); 13 | digitalWrite(A1, HIGH); 14 | digitalWrite(A3, LOW); 15 | // open serial communication: 16 | Serial.begin(9600); 17 | 18 | } 19 | 20 | void loop() { 21 | // read the encoder: 22 | int knob = encoder.read(); 23 | 24 | // if it's changed, take action: 25 | if (knob != prevEncoderPos) { 26 | // get the difference, and save the current value 27 | // for next time: 28 | int difference = knob - prevEncoderPos; 29 | prevEncoderPos = knob; 30 | 31 | // calculate a new setPoint from the difference: 32 | setPoint += (difference / 10.0); 33 | // if the setPoint's at the edge of its range, 34 | // reset the encoder and constrain the setPoint: 35 | if (setPoint <= 10 || setPoint >= 30) { 36 | encoder.write(0); 37 | prevEncoderPos = 0; 38 | setPoint = constrain(setPoint, 10.0, 30.0); 39 | } 40 | } 41 | 42 | 43 | // read the value from the sensor: 44 | int tempSensor = analogRead(A2); 45 | // convert the reading to millivolts: 46 | float voltage = tempSensor * (5000 / 1024); 47 | // convert the millivolts to temperature celsius: 48 | float temperature = (voltage - 500) / 10; 49 | // If the temperature of the setPoint 50 | // has changed enough, send the values out: 51 | if ( (abs(temperature - previousTemp) > 0.5) || 52 | (abs(setPoint - prevSetPoint) > 0.5)) { 53 | Serial.print(setPoint); 54 | Serial.print(","); 55 | Serial.println(temperature); 56 | // save current values for next time: 57 | previousTemp = temperature; 58 | prevSetPoint = setPoint; 59 | } 60 | 61 | // if data comes in, it'll be the server 62 | // sending you an updated setPoint. Parse it: 63 | while (Serial.available() > 0) { 64 | float incoming = Serial.parseFloat(); 65 | if (incoming != 0) { 66 | setPoint = incoming; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToBluetoothSerial/css/style.css: -------------------------------------------------------------------------------- 1 | #fwdButton { 2 | position: fixed; 3 | top: 10px; 4 | left: 160px; 5 | } 6 | #backButton { 7 | position: fixed; 8 | top: 150px; 9 | left: 170px; 10 | } 11 | #urButton { 12 | position: fixed; 13 | top: 60px; 14 | left: 10px; 15 | } 16 | #rButton { 17 | position: fixed; 18 | top: 90px; 19 | left: 40px; 20 | } 21 | #ulButton { 22 | position: fixed; 23 | top: 60px; 24 | left: 280px; 25 | } 26 | #lButton { 27 | position: fixed; 28 | top: 90px; 29 | left: 310px; 30 | } 31 | #stopButton { 32 | position: fixed; 33 | top: 60px; 34 | left: 170px; 35 | } 36 | #endButton { 37 | position: fixed; 38 | top: 90px; 39 | left: 130px; 40 | } -------------------------------------------------------------------------------- /NetworkExamples/nodeToBluetoothSerial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToBluetoothSerial/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | nodeToBluetoothSerial 3 | a node.js app to read take requests and send as serial data 4 | based on restToSerial example 5 | requires: 6 | * node.js (http://nodejs.org/) 7 | * express.js (http://expressjs.com/) 8 | * serialport.js (https://github.com/voodootikigod/node-serialport) 9 | 10 | based on the core examples for socket.io and serialport.js, and restToSerial.js 11 | 12 | created 30 Jan 2014 13 | modified 4 Feb 2014 14 | by Tom Igoe 15 | 16 | */ 17 | 18 | var serialport = require("serialport"), // include the serialport library 19 | SerialPort = serialport.SerialPort, // make a local instance of serial 20 | express = require('express'), // make an instance of express 21 | url = 'http://localhost:8080'; // URL to open in the browser 22 | 23 | var app = express(), // start Express framework 24 | server = require('http').createServer(app); // start an HTTP server 25 | 26 | // configure server to serve static files from 27 | // /js so you can use zepto, and /css, so you can use css: 28 | app.use('/js', express.static(__dirname + '/js')); 29 | app.use('/css', express.static(__dirname + '/css')); 30 | 31 | 32 | // third word of the command line is serial port name: 33 | var portName = process.argv[2]; 34 | // print out the port you're listening on: 35 | console.log("opening serial port: " + portName); 36 | 37 | // listen for incoming requests on the server: 38 | server.listen(8080); 39 | console.log("Listening for new clients on port 8080"); 40 | 41 | // open the serial port. Uses the command line parameter: 42 | var myPort = new SerialPort(portName, { 43 | // look for return and newline at the end of each data packet: 44 | parser: serialport.parsers.readline("\r\n") 45 | }); 46 | 47 | /* The rest of the functions are event-driven. 48 | They only get called when the server gets incoming GET requests: 49 | */ 50 | 51 | // respond to web GET requests with the index.html page: 52 | app.get('/', function (request, response) { 53 | response.sendfile(__dirname + '/index.html'); 54 | }); 55 | 56 | 57 | // take anything that begins with /data/: 58 | app.get('/data/*', function (request, response) { 59 | // after /data/ comes the rest of the request: 60 | var data = request.params[0]; 61 | 62 | // send it out the serial port: 63 | myPort.write(data); 64 | // send an HTTP header to the client: 65 | response.writeHead(200, {'Content-Type': 'text/html'}); 66 | // send the data and close the connection: 67 | response.end(data); 68 | }); 69 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToBluetoothSerial/js/buttonControls.js: -------------------------------------------------------------------------------- 1 | function setup() { 2 | fwdButton.addEventListener('click', sendButton, false); 3 | backButton.addEventListener('click', sendButton, false); 4 | urButton.addEventListener('click', sendButton, false); 5 | rButton.addEventListener('click', sendButton, false); 6 | ulButton.addEventListener('click', sendButton, false); 7 | lButton.addEventListener('click', sendButton, false); 8 | stopButton.addEventListener('click', sendButton, false); 9 | endButton.addEventListener('click', sendButton, false); 10 | } 11 | 12 | function sendButton(event) { 13 | $.get("/data/"+ this.value); 14 | } 15 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToBluetoothSerial/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodeToBluetoothSerial", 3 | "version": "0.0.1", 4 | "description" : "A browser-to-serial application using RESTful URL calls", 5 | "keywords": "serial, node-serialport", 6 | "author": { 7 | "name":"Tom Igoe" 8 | }, 9 | "dependencies": { 10 | "serialport": "1.1.x", 11 | "express": "3.x", 12 | "open": ">=0.0.4" 13 | }, 14 | "engines": { 15 | "node": "0.10.x", 16 | "npm": "1.3.x" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToFile/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [NodeExamples repository](https://github.com/tigoe/NodeExamples) -------------------------------------------------------------------------------- /NetworkExamples/nodeToProcessing/ADXL326/ADXL326.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ADXL326 3 | 4 | Reads an ADXL326 3-axis accelerometer from Adafruit. 5 | Sends the results as a JSON-formatted string like so: 6 | {x:345, y:432, z:234}\n 7 | 8 | created 16 Oct 2012 9 | by Tom Igoe 10 | */ 11 | 12 | //Set up pins for Adafruit ADXL326 breakout board: 13 | const int Vin = A0; 14 | const int Gnd = A2; 15 | const int zPin = A3; 16 | const int yPin = A4; 17 | const int xPin = A5; 18 | 19 | void setup() { 20 | Serial.begin(9600); 21 | // initialize power and ground pins for accelerometer: 22 | pinMode(Vin, OUTPUT); 23 | pinMode(Gnd, OUTPUT); 24 | digitalWrite(Vin, HIGH); 25 | digitalWrite(Gnd, LOW); 26 | } 27 | 28 | void loop() { 29 | // read sensors: 30 | int x = analogRead(xPin); 31 | delay(1); 32 | int y = analogRead(yPin); 33 | delay(1); 34 | int z = analogRead(zPin); 35 | 36 | // form a JSON-formatted string: 37 | String jsonString = "{x:"; 38 | jsonString += x; 39 | jsonString +=",y:"; 40 | jsonString += y; 41 | jsonString +=",z:"; 42 | jsonString += z; 43 | jsonString +="}"; 44 | 45 | // print it: 46 | Serial.println(jsonString); 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToProcessing/README.md: -------------------------------------------------------------------------------- 1 | nodeToProcessing.js 2 | 3 | A serial-to-node-to-Processing example using node.js, node-serialport. 4 | 5 | To use this, you should read up on node.js 6 | 7 | To install it: 8 | * make sure you've installed node.js 9 | * either clone the project in git or download it 10 | * from the command line,change directories to the directory where you downloaded the project 11 | 12 | Enter the following: 13 | 14 | npm install 15 | 16 | You should end up with a new directory called node_modules, which will include socket.io, node-serialport, and express.js. 17 | 18 | Install ADXL326.ino onto an Arduino Uno or Leonardo or Mega that has an ADXL326 acclerometer breakout board from Adafruit attached. 19 | 20 | To run the server, enter: 21 | 22 | node nodeToProcessing.js 23 | 24 | Then open jsonProcessing.pde in Processing 2.0 or later, and run it. You should get a nice scatter graph of the X and Y coordinates from the acceleromter. -------------------------------------------------------------------------------- /NetworkExamples/nodeToProcessing/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | nodeToProcessing.js 3 | a node.js app to respond to HTTP requests from Processing 4 | requires: 5 | * node.js (http://nodejs.org/) 6 | * express.js (http://expressjs.com/) 7 | * serialport.js (https://github.com/voodootikigod/node-serialport) 8 | 9 | See jsonProcessing.pde in this project for a Processing sketch that 10 | wil act as a client to this app. 11 | 12 | See also ADXL326.ino for an Arduino sketch that will send a 13 | JSON-formatted string to this app via serial communication. 14 | 15 | created 16 Oct 2012 16 | by Tom Igoe 17 | 18 | */ 19 | 20 | var serialport = require("serialport"), // include the serialport library 21 | SerialPort = serialport.SerialPort, // make a local instance of serial 22 | app = require('express')(); // start Express framework 23 | 24 | var sensorData = {}; // object to hold what goes out to the client 25 | 26 | app.listen(8080); // listen for incoming requests on the server 27 | 28 | console.log("Listening for new clients on port 8080"); 29 | 30 | // open the serial port. Change the name to the name of your port, just like in Processing and Arduino: 31 | var myPort = new SerialPort("/dev/cu.usbmodem621", { 32 | // look for return and newline at the end of each data packet: 33 | parser: serialport.parsers.readline("\r\n") 34 | }); 35 | 36 | myPort.on('data', function (data) { 37 | var values = []; 38 | // get the serial string and put it in the sensorData object: 39 | sensorData = data; 40 | }); 41 | 42 | // respond to web GET requests with the index.html page: 43 | app.get('/', function (request, response) { 44 | response.sendfile(__dirname + '/index.html'); 45 | }); 46 | 47 | // respond to web GET requests for /sensors with the sensor data: 48 | app.get('/sensors', function (request, response) { 49 | response.send(sensorData); 50 | }); 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToProcessing/jsonProcessing/jsonProcessing.pde: -------------------------------------------------------------------------------- 1 | /* 2 | jsonProcessing 3 | 4 | Makes an HTTP request using loadStrings to get sensor data 5 | from a node.js server. Expects the following JSON format: 6 | {x:345, y:432, z:234}\n 7 | 8 | Uses Jer Thorp's JSON library for Processing, available here: 9 | http://www.blprnt.com/processing/json.zip 10 | Details: 11 | http://blog.blprnt.com/blog/blprnt/processing-json-the-new-york-times 12 | Java JSON docs: 13 | http://www.json.org/java/ 14 | 15 | created 16 Oct 2012 16 | by Tom Igoe 17 | */ 18 | 19 | import org.json.*; // import JSON library 20 | 21 | String URL = "http://localhost:8080/sensors"; 22 | 23 | void setup() { 24 | // set up graphics: 25 | size(400, 400); 26 | background(#002379); 27 | noStroke(); 28 | } 29 | 30 | void draw() { 31 | // get coordinates from server: 32 | int[] coordinates = getData(URL); 33 | 34 | // map to the size of the screen: 35 | float x = map(coordinates[0], 250, 450, 0, width); 36 | float y = map(coordinates[1], 250, 450, 0, height); 37 | 38 | // make a fill color and draw a point 39 | fill(255); 40 | ellipse(x, y, 1, 1); 41 | } 42 | 43 | int[] getData(String request) { 44 | int results[] = new int[3]; // array to return results 45 | // make a HTTP request, and join the resulting array back into a string: 46 | String data = join(loadStrings(request), ""); 47 | 48 | // try to parse the resulting JSON into an array: 49 | try { 50 | JSONObject sensorData = new JSONObject(data); 51 | results[0] = sensorData.getInt("x"); 52 | results[1] = sensorData.getInt("y"); 53 | results[2] = sensorData.getInt("z"); 54 | } 55 | catch (JSONException e) { 56 | println ("There was an error parsing the JSONObject."); 57 | } 58 | // return the array: 59 | return results; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /NetworkExamples/nodeToProcessing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodeToProcessing", 3 | "version": "0.1.0", 4 | "description" : "simple serial-to-broswer server application", 5 | "author": { 6 | "name":"Tom Igoe" 7 | }, 8 | "dependencies": { 9 | "serialport": "1.1.x", 10 | "express": "3.x" 11 | }, 12 | "engines": { 13 | "node": "0.10.x", 14 | "npm": "1.3.x" 15 | } 16 | } -------------------------------------------------------------------------------- /NetworkExamples/nodeTraceroute/readme.md: -------------------------------------------------------------------------------- 1 | This example has been moved to my [NodeExamples repository](https://github.com/tigoe/NodeExamples) -------------------------------------------------------------------------------- /Networking-Scripts/C2_Simulator_Http_Server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Author: AGDC Services 5 | Website: AGDCservices.com 6 | Date: 20210503 7 | 8 | 9 | This is a Command and Control (C2) simulator for HTTP traffic 10 | It is a framework that you can fill out to simulate any 11 | C2 server to aid in exercising and analyzing target malware commands 12 | 13 | Usage: 14 | - Fill in the variables at the top of main 15 | - Fill in desired HTTP response in the do_GET and do_POST functions 16 | - Run the file from a command prompt 17 | ''' 18 | 19 | 20 | 21 | import ssl 22 | from http.server import BaseHTTPRequestHandler, HTTPServer 23 | import sys 24 | import struct 25 | import base64 26 | import cgi 27 | 28 | 29 | ''' 30 | The following two variables are only needed if TLS is enabled 31 | 32 | 33 | Details: 34 | - Create the key and cert on the host where this script will be run 35 | - fill in the variables below with the key / cert paths 36 | - set the bDoTls variable in the main function to True 37 | 38 | one method to create a TLS key / cert is to use openssl on linux with the following commands 39 | all of the default options can be used when creating the x509 certificate 40 | - openssl genpkey -out -algorithm RSA -pkeyopt rsa_keygen_bits: 41 | - openssl req -new -x509 -key -days 7200 -out 42 | 43 | example: 44 | openssl genpkey -out key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 45 | openssl req -new -x509 -key key.pem -days 7200 -out cert.cert 46 | ''' 47 | 48 | gTlsKeyFilePath = '' 49 | gTlsCertFilePath = '' 50 | 51 | 52 | 53 | def main(): 54 | ''' 55 | main function to start http c2 server 56 | ''' 57 | 58 | # initialize variables 59 | domain = '0.0.0.0' # ip address to listen on 60 | port = 80 # port number to listen on 61 | 62 | # boolean indicating if HTTPS should be used 63 | # fill in the gTlsKeyFilePath and gTlsCertFilePath variables at top of simulator 64 | # if TLS is enabled 65 | bDoTls = False 66 | 67 | # error check 68 | if bDoTls == True and (len(gTlsKeyFilePath) == 0 or len(gTlsCertFilePath) == 0): 69 | sys.exit('\n[*] Error: variables gTlsKeyFilePath and gTlsCertFilePath must be used if TLS is enabled') 70 | 71 | 72 | # start http server 73 | Http_Server(domain, port, Http_Handler, bDoTls) 74 | 75 | 76 | 77 | 78 | 79 | def Http_Server(host, port, handlerClass, bDoTls): 80 | ''' 81 | starts a http server to respond to incoming requests 82 | can handle single or infinite based on line commented out 83 | 84 | ''' 85 | 86 | server_class = HTTPServer 87 | httpd = server_class( (host, port), handlerClass) 88 | 89 | if bDoTls == True: 90 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 91 | context.verify_mode = ssl.CERT_NONE 92 | context.load_cert_chain(keyfile=gTlsKeyFilePath, certfile=gTlsCertFilePath) 93 | httpd.socket = context.wrap_socket(httpd.socket, server_side=True) 94 | 95 | 96 | print('Starting Http Server\n') 97 | try: 98 | httpd.serve_forever() 99 | #httpd.handle_request() 100 | except KeyboardInterrupt: 101 | pass 102 | 103 | 104 | 105 | class Http_Handler(BaseHTTPRequestHandler): 106 | ''' 107 | handler class which holds code to build GET / POST response 108 | ''' 109 | 110 | # initialize static class variables 111 | nGetCount = 0 112 | nPostCount = 0 113 | 114 | 115 | def log_message(self, format, *args): 116 | ''' 117 | included so python doesn't print out log messages 118 | ''' 119 | pass 120 | 121 | def _Set_Headers(self, bufSend = None): 122 | self.send_header('Content-type', 'text/html') 123 | self.send_header('Fake_C2_Http_Header', 'text/html') 124 | if bufSend != None: 125 | self.send_header('Content-Length', bufSend.__len__()) 126 | self.end_headers() 127 | 128 | 129 | def do_GET(self): 130 | ''' 131 | respond to GET requests 132 | ''' 133 | 134 | # get url requested in GET requests 135 | host = self.headers['host'] 136 | path = self.path 137 | 138 | self.__class__.nGetCount += 1 139 | print('\nreceived GET request #{:02d} to {:s}{:s}'.format(self.__class__.nGetCount, host, path)) 140 | 141 | 142 | # initialize response data to send 143 | bufSend = b'D' * 16 144 | 145 | 146 | 147 | # send reponse to GET requests 148 | self.send_response(200) # required for real HTTP functions to parse request 149 | if bufSend != None: 150 | self._Set_Headers() 151 | self.wfile.write(bufSend) 152 | 153 | 154 | def do_POST(self): 155 | ''' 156 | respond to POST requests 157 | ''' 158 | 159 | # get POST request parameters of interest 160 | host = self.headers['host'] 161 | path = self.path 162 | #dataLen = int(self.headers.getheader('Content-Length')) 163 | dataLen = int(self.headers['Content-Length']) 164 | ctype, pdict = cgi.parse_header(self.headers['Content-Type']) 165 | if ctype == 'multipart/form-data': 166 | pdict['boundary'] = bytes(pdict['boundary'], 'utf-8') 167 | fieldsDict = cgi.parse_multipart(self.rfile, pdict) 168 | else: 169 | bufRecv = self.rfile.read(dataLen) 170 | 171 | 172 | self.__class__.nPostCount += 1 173 | print('\nreceived POST request #{:02d} to {:s}{:s}'.format(self.__class__.nPostCount, host, path)) 174 | 175 | 176 | # initialize response data to send 177 | bufSend = b'D' * 16 178 | 179 | 180 | 181 | # send response to POST request 182 | self.send_response(200) # required for real HTTP functions to parse request 183 | if bufSend != None: 184 | self._Set_Headers(bufSend) 185 | self.wfile.write(bufSend) 186 | 187 | 188 | def Print_Hexdump(data, displayLen = 16): 189 | ''' 190 | utility function to print the data as a hex dump output 191 | ''' 192 | 193 | lines = [] 194 | for i in range(0, len(data), displayLen): 195 | chars = data[i:(i + displayLen)] 196 | 197 | # get standard output views for ???????? 198 | offset = '{:04x}'.format(i) 199 | hexValues = ' '.join( '{:02x}'.format(i) for i in chars) 200 | asciiValues = ''.join([chr(i) if i in range(0x20, 0x7f) else '.' for i in chars]) 201 | 202 | # add space after every 8 bytes 203 | charLen = 3 # include space included between hex values 204 | hexValues = ' '.join( [hexValues[i:(i + charLen*8) ] for i in range(0, len(hexValues) - 0, charLen*8)] ) 205 | charLen = 1 # no space includeed in ascii values 206 | asciiValues = ' '.join( [asciiValues[i:(i + charLen*8)] for i in range(0, len(asciiValues) - 0, charLen*8) ] ) 207 | 208 | # combine all parts of the hexdump into a single list 209 | spaceAdded = ((3 * displayLen) - 1) / (3 * 8) 210 | lines.append('{:s} {:{}s} {:s}'.format(offset, hexValues, displayLen * 3 + spaceAdded, asciiValues)) 211 | 212 | 213 | print('\n'.join(lines)) 214 | return '\n'.join(lines) 215 | 216 | 217 | 218 | 219 | if __name__ == '__main__': 220 | main() -------------------------------------------------------------------------------- /Networking-Scripts/C2_Simulator_Tcp_Client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Author: AGDC Services 5 | Website: AGDCservices.com 6 | Date: 20210501 7 | 8 | 9 | This is a Command and Control(C2) Client simulator for TCP traffic 10 | 11 | Usage: 12 | - Fill in the variables at the top of main 13 | - write your custom C2 code in the "Start of C2 Simulation Code" 14 | section in main after the client class is instantiated. 15 | Use the client instance to access the utility 16 | networking functions. The available functions to the client instance 17 | are listed at the top of the "Start of C2 Simulation Code" section 18 | - Run the file from a command prompt using python 3 19 | ''' 20 | 21 | 22 | 23 | import ssl 24 | import socket 25 | import sys 26 | import struct 27 | import base64 28 | import time 29 | 30 | ''' 31 | The following two variables are only needed if TLS is enabled 32 | 33 | 34 | Details: 35 | - Create the key and cert on the host where this script will be run 36 | - fill in the variables below with the key / cert paths 37 | - set the bDoTls variable in the main function to True 38 | 39 | one method to create a TLS key / cert is to use openssl on linux with the following commands 40 | all of the default options can be used when creating the x509 certificate 41 | - openssl genpkey -out -algorithm RSA -pkeyopt rsa_keygen_bits: 42 | - openssl req -new -x509 -key -days 7200 -out 43 | 44 | example: 45 | openssl genpkey -out key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 46 | openssl req -new -x509 -key key.pem -days 7200 -out cert.cert 47 | ''' 48 | 49 | gTlsKeyFilePath = r'' 50 | gTlsCertFilePath = r'' 51 | 52 | 53 | 54 | def main(): 55 | ''' 56 | main function to simulate C2 client network traffic 57 | ''' 58 | 59 | ############################################ 60 | # Initialization Variables 61 | ############################################ 62 | 63 | # initialize variables 64 | connectingIp = '' # string of dotted decimal ip address to connect to, e.g. '10.10.10.10' 65 | port = 80 # decimal port number to connect to 66 | 67 | # boolean indicating if TLS should be used 68 | # fill in the gTlsKeyFilePath and gTlsCertFilePath variables at top of simulator 69 | # if TLS is enabled 70 | bDoTls = False 71 | 72 | ############################################ 73 | 74 | 75 | 76 | # error check 77 | if bDoTls == True and (len(gTlsKeyFilePath) == 0 or len(gTlsCertFilePath) == 0): 78 | sys.exit('\n[*] ERROR: variables gTlsKeyFilePath and gTlsCertFilePath must be used if TLS is enabled') 79 | 80 | 81 | ############################################ 82 | # Start Of C2 Simulation Code 83 | ############################################ 84 | 85 | # 86 | # Built in Utility Function Prototypes 87 | # See function headers for usage details 88 | # 89 | # Print_Hexdump(byteString) 90 | # 91 | # Client(connectingIp, port, bDoTls) # Class Constructor 92 | # .Send(buf) 93 | # .Recv_Len(nLen) 94 | # .Recv_Len_Prepended(lengthOfLengthField, bLittleEndian) 95 | # .Recv_Delim(delim) 96 | # .Socket_Close() 97 | # 98 | 99 | 100 | # initialize the client instance 101 | client = Client(connectingIp, port, bDoTls) 102 | 103 | 104 | 105 | 106 | 107 | 108 | class Client: 109 | # Client class which contains all the basic networking 110 | # utility functions needed to simulate a C2 client 111 | 112 | def __init__(self, host, port, bDoTls): 113 | 114 | print('Starting TCP Client\n') 115 | 116 | # create a socket 117 | s = socket.socket( socket.AF_INET, socket.SOCK_STREAM) 118 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 119 | 120 | 121 | # conenct to the tcp server 122 | s.connect((host, port)) 123 | 124 | 125 | # if TLS is needed, wrap the socket in the key / cert 126 | # declared in the global variables at the top of the script 127 | if bDoTls == True: 128 | context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) 129 | context.check_hostname = False 130 | context.verify_mode = ssl.CERT_NONE 131 | context.load_cert_chain(keyfile=gTlsKeyFilePath, certfile=gTlsCertFilePath) 132 | s = context.wrap_socket(s, server_side=False) 133 | 134 | 135 | # set instance connection variable to current socket 136 | # using self.conn variable purely for code reuse in the send / recv 137 | # functions for both the Client / Server scripts 138 | self.conn = s 139 | 140 | 141 | 142 | def Send(self, buf): 143 | ''' 144 | send entire buffer 145 | 146 | buf must be a byte string 147 | ''' 148 | 149 | # error check 150 | if isinstance(buf, bytes) == False: 151 | sys.exit('\n[*] ERROR: buf must be a byte string for Send function') 152 | 153 | self.conn.sendall(buf) 154 | 155 | 156 | def Recv_Len(self, nLen): 157 | ''' 158 | receives a fixed length (nLen) number of bytes 159 | and returns a byte string of the received bytes 160 | ''' 161 | 162 | result = b'' 163 | bytesRemaining = nLen 164 | while bytesRemaining > 0: 165 | result += self.conn.recv(bytesRemaining) 166 | bytesRemaining = nLen - len(result) 167 | 168 | 169 | return result 170 | 171 | 172 | 173 | def Recv_Len_Prepended(self, lengthOfLengthField, bLittleEndian): 174 | ''' 175 | receives a packet assuming the packet length preceeds the data 176 | drops the length part of the bytes and just returns the packet data 177 | returns a byte string of the received packet data 178 | 179 | lengthOfLengthField should be the number of bytes used to store 180 | the length of the data portion, e.g. 1,2,4 bytes 181 | 182 | bLittleEndian refers to the endianess of the lengthOfLengthField 183 | ''' 184 | 185 | # determine how to unpack the length field based on function arguments 186 | endiness = '<' if bLittleEndian == True else '>' 187 | sizeIndicator = {1:'B', 2:'H', 4:'I'} 188 | 189 | # error check 190 | if lengthOfLengthField not in sizeIndicator: 191 | sys.exit('\n[*] error: lengthOfLengthField not valid for this function') 192 | 193 | 194 | # build the format string to specify how to unpack the data length 195 | formatStr = endiness + sizeIndicator[lengthOfLengthField] 196 | 197 | # get the length of the data segment 198 | dataLen = self.Recv_Len(lengthOfLengthField) 199 | 200 | # transform the length from string to int 201 | dataLen = struct.unpack(formatStr, dataLen)[0] 202 | 203 | # get the actual data 204 | data = self.Recv_Len(dataLen) 205 | 206 | return data 207 | 208 | 209 | 210 | def Recv_Delim(self, delim): 211 | ''' 212 | receives a packet until you receive the terminating deliminator 213 | delim must be a byte string 214 | returns the received bytes, minus the deliminator, as a byte string 215 | ''' 216 | 217 | # error check 218 | if isinstance(delim, bytes) == False: 219 | sys.exit('\n[*] ERROR: delim must be a byte string for Recv_Delim function') 220 | 221 | result = b'' 222 | while result.endswith(delim) == False: 223 | result += self.Recv_Len(1) 224 | 225 | result = result[:-len(delim)] 226 | 227 | return result 228 | 229 | 230 | def Socket_Close(self): 231 | ''' 232 | closes the socket 233 | ''' 234 | 235 | if self.conn is not None: 236 | self.conn.close() 237 | 238 | 239 | 240 | 241 | def Print_Hexdump(data, displayLen = 16): 242 | ''' 243 | utility function to print the data as a hex dump output 244 | ''' 245 | 246 | # error check 247 | if isinstance(data, bytes) == False: 248 | sys.exit('\n[*] ERROR: data must be a byte string for Print_Hexdump function') 249 | 250 | 251 | lines = [] 252 | for i in range(0, len(data), displayLen): 253 | chars = data[i:(i + displayLen)] 254 | 255 | # get standard output views for ???????? 256 | offset = '{:04x}'.format(i) 257 | hexValues = ' '.join( '{:02x}'.format(i) for i in chars) 258 | asciiValues = ''.join([chr(i) if i in range(0x20, 0x7f) else '.' for i in chars]) 259 | 260 | # add space after every 8 bytes 261 | charLen = 3 # include space included between hex values 262 | hexValues = ' '.join( [hexValues[i:(i + charLen*8) ] for i in range(0, len(hexValues) - 0, charLen*8)] ) 263 | charLen = 1 # no space includeed in ascii values 264 | asciiValues = ' '.join( [asciiValues[i:(i + charLen*8)] for i in range(0, len(asciiValues) - 0, charLen*8) ] ) 265 | 266 | # combine all parts of the hexdump into a single list 267 | spaceAdded = ((3 * displayLen) - 1) / (3 * 8) 268 | lines.append('{:s} {:{}s} {:s}'.format(offset, hexValues, displayLen * 3 + spaceAdded, asciiValues)) 269 | 270 | 271 | print('\n'.join(lines)) 272 | return '\n'.join(lines) 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | if __name__ == '__main__': 281 | main() -------------------------------------------------------------------------------- /Networking-Scripts/C2_Simulator_Tcp_Server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | Author: AGDC Services 5 | Website: AGDCservices.com 6 | Date: 20210501 7 | 8 | 9 | This is a Command and Control(C2) server simulator for TCP traffic 10 | 11 | Usage: 12 | - Fill in the variables at the top of main 13 | - write your custom C2 code in the "Start of C2 Simulation Code" 14 | section in main after the client class is instantiated. 15 | Use the server instance to access the utility 16 | networking functions. The available functions to the server instance 17 | are listed at the top of the "Start of C2 Simulation Code" section 18 | - Run the file from a command prompt using python 3 19 | ''' 20 | 21 | 22 | 23 | import ssl 24 | import socket 25 | import sys 26 | import struct 27 | import base64 28 | import time 29 | 30 | ''' 31 | The following two variables are only needed if TLS is enabled 32 | 33 | 34 | Details: 35 | - Create the key and cert on the host where this script will be run 36 | - fill in the variables below with the key / cert paths 37 | - set the bDoTls variable in the main function to True 38 | 39 | one method to create a TLS key / cert is to use openssl on linux with the following commands 40 | all of the default options can be used when creating the x509 certificate 41 | - openssl genpkey -out -algorithm RSA -pkeyopt rsa_keygen_bits: 42 | - openssl req -new -x509 -key -days 7200 -out 43 | 44 | example: 45 | openssl genpkey -out key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 46 | openssl req -new -x509 -key key.pem -days 7200 -out cert.cert 47 | ''' 48 | 49 | gTlsKeyFilePath = r'' 50 | gTlsCertFilePath = r'' 51 | 52 | 53 | 54 | def main(): 55 | ''' 56 | main function to simulate C2 server network traffic 57 | ''' 58 | 59 | ############################################ 60 | # Initialization Variables 61 | ############################################ 62 | 63 | # initialize variables 64 | listeningIp = '0.0.0.0' # string of dotted decimal ip address to listen on, e.g. '0.0.0.0' for all IPs 65 | port = 80 # decimal port number to listen on 66 | 67 | # boolean indicating if TLS should be used 68 | # fill in the gTlsKeyFilePath and gTlsCertFilePath variables at top of simulator 69 | # if TLS is enabled 70 | bDoTls = False 71 | 72 | ############################################ 73 | 74 | 75 | 76 | # error check 77 | if bDoTls == True and (len(gTlsKeyFilePath) == 0 or len(gTlsCertFilePath) == 0): 78 | sys.exit('\n[*] ERROR: variables gTlsKeyFilePath and gTlsCertFilePath must be used if TLS is enabled') 79 | 80 | 81 | ############################################ 82 | # Start Of C2 Simulation Code 83 | ############################################ 84 | 85 | # 86 | # Built in Utility Function Prototypes 87 | # See function headers for usage details 88 | # 89 | # Print_Hexdump(byteString) 90 | # 91 | # Server(listeningIp, port, bDoTls) # Class Constructor 92 | # .Send(buf) 93 | # .Recv_Len(nLen) 94 | # .Recv_Len_Prepended(lengthOfLengthField, bLittleEndian) 95 | # .Recv_Delim(delim) 96 | # .Socket_Close() 97 | # 98 | 99 | 100 | # initialize the server instance 101 | server = Server(listeningIp, port, bDoTls) 102 | 103 | 104 | 105 | 106 | 107 | 108 | class Server: 109 | # Server class which contains all the basic networking 110 | # utility functions needed to simulate a C2 server 111 | 112 | def __init__(self, host, port, bDoTls): 113 | 114 | print('Starting TCP Server\n') 115 | 116 | # create a socket 117 | s = socket.socket( socket.AF_INET, socket.SOCK_STREAM) 118 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 119 | 120 | # bind to the port and start accepting connections 121 | s.bind( (host, port) ) 122 | s.listen(1) 123 | self.conn, clientAddr = s.accept() 124 | 125 | # if TLS is needed, wrap the socket in the key / cert 126 | # declared in the global variables at the top of the script 127 | if bDoTls == True: 128 | context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) 129 | context.verify_mode = ssl.CERT_NONE 130 | context.load_cert_chain(keyfile=gTlsKeyFilePath, certfile=gTlsCertFilePath) 131 | ss = context.wrap_socket(self.conn, server_side=True) 132 | self.conn = ss 133 | 134 | 135 | def Send(self, buf): 136 | ''' 137 | send entire buffer 138 | 139 | buf must be a byte string 140 | ''' 141 | 142 | # error check 143 | if isinstance(buf, bytes) == False: 144 | sys.exit('\n[*] ERROR: buf must be a byte string for Send function') 145 | 146 | self.conn.sendall(buf) 147 | 148 | 149 | def Recv_Len(self, nLen): 150 | ''' 151 | receives a fixed length (nLen) number of bytes 152 | and returns a byte string of the received bytes 153 | ''' 154 | 155 | result = b'' 156 | bytesRemaining = nLen 157 | while bytesRemaining > 0: 158 | result += self.conn.recv(bytesRemaining) 159 | bytesRemaining = nLen - len(result) 160 | 161 | 162 | return result 163 | 164 | 165 | 166 | def Recv_Len_Prepended(self, lengthOfLengthField, bLittleEndian): 167 | ''' 168 | receives a packet assuming the packet length preceeds the data 169 | drops the length part of the bytes and just returns the packet data 170 | returns a byte string of the received packet data 171 | 172 | lengthOfLengthField should be the number of bytes used to store 173 | the length of the data portion, e.g. 1,2,4 bytes 174 | 175 | bLittleEndian refers to the endianess of the lengthOfLengthField 176 | ''' 177 | 178 | # determine how to unpack the length field based on function arguments 179 | endiness = '<' if bLittleEndian == True else '>' 180 | sizeIndicator = {1:'B', 2:'H', 4:'I'} 181 | 182 | # error check 183 | if lengthOfLengthField not in sizeIndicator: 184 | sys.exit('\n[*] error: lengthOfLengthField not valid for this function') 185 | 186 | 187 | # build the format string to specify how to unpack the data length 188 | formatStr = endiness + sizeIndicator[lengthOfLengthField] 189 | 190 | # get the length of the data segment 191 | dataLen = self.Recv_Len(lengthOfLengthField) 192 | 193 | # transform the length from string to int 194 | dataLen = struct.unpack(formatStr, dataLen)[0] 195 | 196 | # get the actual data 197 | data = self.Recv_Len(dataLen) 198 | 199 | return data 200 | 201 | 202 | 203 | def Recv_Delim(self, delim): 204 | ''' 205 | receives a packet until you receive the terminating deliminator 206 | delim must be a byte string 207 | returns the received bytes, minus the deliminator, as a byte string 208 | ''' 209 | 210 | # error check 211 | if isinstance(delim, bytes) == False: 212 | sys.exit('\n[*] ERROR: delim must be a byte string for Recv_Delim function') 213 | 214 | result = b'' 215 | while result.endswith(delim) == False: 216 | result += self.Recv_Len(1) 217 | 218 | result = result[:-len(delim)] 219 | 220 | return result 221 | 222 | 223 | def Socket_Close(self): 224 | ''' 225 | closes the socket 226 | ''' 227 | 228 | if self.conn is not None: 229 | self.conn.close() 230 | 231 | 232 | 233 | 234 | def Print_Hexdump(data, displayLen = 16): 235 | ''' 236 | utility function to print the data as a hex dump output 237 | ''' 238 | 239 | # error check 240 | if isinstance(data, bytes) == False: 241 | sys.exit('\n[*] ERROR: data must be a byte string for Print_Hexdump function') 242 | 243 | 244 | lines = [] 245 | for i in range(0, len(data), displayLen): 246 | chars = data[i:(i + displayLen)] 247 | 248 | # get standard output views for ???????? 249 | offset = '{:04x}'.format(i) 250 | hexValues = ' '.join( '{:02x}'.format(i) for i in chars) 251 | asciiValues = ''.join([chr(i) if i in range(0x20, 0x7f) else '.' for i in chars]) 252 | 253 | # add space after every 8 bytes 254 | charLen = 3 # include space included between hex values 255 | hexValues = ' '.join( [hexValues[i:(i + charLen*8) ] for i in range(0, len(hexValues) - 0, charLen*8)] ) 256 | charLen = 1 # no space includeed in ascii values 257 | asciiValues = ' '.join( [asciiValues[i:(i + charLen*8)] for i in range(0, len(asciiValues) - 0, charLen*8) ] ) 258 | 259 | # combine all parts of the hexdump into a single list 260 | spaceAdded = ((3 * displayLen) - 1) / (3 * 8) 261 | lines.append('{:s} {:{}s} {:s}'.format(offset, hexValues, displayLen * 3 + spaceAdded, asciiValues)) 262 | 263 | 264 | print('\n'.join(lines)) 265 | return '\n'.join(lines) 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | if __name__ == '__main__': 274 | main() -------------------------------------------------------------------------------- /Networking-Scripts/README.md: -------------------------------------------------------------------------------- 1 | # Networking Scripts 2 | > Networking scripts to aid in malware reverse engineering 3 | ## C2_Simulator_Http_Server.py 4 | This is a Command and Control (C2) simulator for HTTP traffic. It is a framework that you can fill out to simulate any C2 server that uses HTTP traffic to aid in exercising and analyzing target malware commands. See the script for additional usage instructions. 5 | ## C2_Simulator_Tcp_Client.py 6 | This is a Command and Control (C2) client simulator for TCP traffic. It is a framework that includes a number of pre-built utility functions you can use to simulate any C2 client that uses TCP traffic to aid in exercising and analyzing target malware commands. See the script for additional usage instructions. 7 | ## C2_Simulator_Tcp_Server.py 8 | This is a Command and Control (C2) server simulator for TCP traffic. It is a framework that includes a number of pre-built utility functions you can use to simulate any C2 server that uses TCP traffic to aid in exercising and analyzing target malware commands. See the script for additional usage instructions. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Networking & Cybersecurity 2 | > Welcome to the world of Networking. 3 | An ongoing curated collection of awesome software, libraries, frameworks, talks & videos, best practices, learning tutorials and important practical resources about networking in cybersecurity. Thanks to all contributors, you're awesome and wouldn't be possible without you! Our goal is to build a categorized community-driven collection of very well-known resources. 4 | 5 | 6 | 7 | ## `Table of Contents` 8 | - [Network Foundations](#network-foundations) 9 | - [TCP/IP Protocols](#tcpip-protocols) 10 | - [Courses](#courses) 11 | - [Tutorials](#tutorials) 12 | - [Books](#books) 13 | - [Software](#software) 14 | - [Certifications](#certifications) 15 | - [Miscellaneous](#miscellaneous) 16 | - [Network Design Resources](#network-design-resources) 17 | - [Network Implementation](#network-implementation) 18 | - [Routing](#routing) 19 | - [Switching](#switching) 20 | - [VPN](#vpn) 21 | - [Network Services](#network-services) 22 | - [Network Simulators and Traffic Generators](#network-simulators-and-traffic-generators) 23 | - [Network Operations](#network-operations) 24 | - [Network Change Management](#network-change-management) 25 | - [Network Automation](#network-automation) 26 | - [Network Monitoring](#network-monitoring) 27 | - [Security Monitoring](#security-monitoring) 28 | - [Network Inventory](#network-inventory) 29 | - [Related resources](#related-resources) 30 | - [DevNet Tools](#devnet-tools) 31 | - [DevNet Monitoring](#devnet-monitoring) 32 | - [DevNet Knowledgebase](#devnet-knowledgebase) 33 | - [DevNet Inventory](#devnet-inventory) 34 | - [Knowledge Resources](#knowledge-resources) 35 | - [License](#license) 36 | 37 | 38 | ## `Network Foundations` 39 | 40 | - [Computer networking](https://www.cisco.com/c/en/us/solutions/enterprise-networks/what-is-computer-networking.html) refers to connected **computing devices** (such as laptops, desktops, servers, smartphones, and tablets) and an ever-expanding array of **IoT devices** (such as cameras, door locks, doorbells, refrigerators, audio/visual systems, thermostats, and various sensors) that communicate with one another. 41 | 42 | ![network](https://github.com/paulveillard/cybersecurity-networking/blob/main/img/network.png) 43 | 44 | ## `TCP/IP Protocols` 45 | 46 | **Note**: Links without description are official RFCs from the Internet Engineering Task Force (IETF). 47 | 48 | - DNS 49 | - [DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION](https://www.ietf.org/rfc/rfc1035.txt) 50 | 51 | ![dns](https://github.com/paulveillard/cybersecurity-networking/blob/main/img/dns.png) 52 | 53 | > DNS, or the Domain Name System, translates human readable domain names (for example, www.amazon.com) to machine readable IP addresses (for example, 192.0.2.44). 54 | 55 | 56 | - DHCP 57 | - [DYNAMIC HOST CONFIGURATION PROTOCOL](https://www.ietf.org/rfc/rfc2131.txt) 58 | 59 | ![dhcp](https://github.com/paulveillard/cybersecurity-networking/blob/main/img/dhcp.png) 60 | 61 | **Dynamic Host Configuration Protocol, or DHCP,** is used to provide quick and centralized management of IP addresses and other TCP/IP settings on your network. These are things like host IP address, subnet mask, DNS settings, default gateway address, and so on (I call these “IP configuration settings”). When you power on your computer, a DHCP server likely provides these IP configuration settings to you. Even if you don’t have a stand-alone DHCP server, your default gateway likely has its own DHCP server feature. 62 | 63 | **DHCP really makes network management a lot easier. DHCP eliminates the need for manually assigning IP addresses to our devices. DHCP port number for server is 67 and for the client is 68. It is a Client server protocol which uses UDP services** 64 | 65 | - FTP 66 | - [FILE TRANSFER PROTOCOL (FTP)](https://www.ietf.org/rfc/rfc959.txt) 67 | ![ftp](https://github.com/paulveillard/cybersecurity-networking/blob/main/img/ftp.png) 68 | 69 | - HTTP 70 | - [Hypertext Transfer Protocol -- HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt) 71 | - [Hypertext Transfer Protocol Version 2 (HTTP/2)](https://www.ietf.org/rfc/rfc7540.txt) 72 | - UDP 73 | - [User Datagram Protocol](https://www.ietf.org/rfc/rfc768.txt) 74 | - TCP 75 | - [TRANSMISSION CONTROL PROTOCOL](https://www.ietf.org/rfc/rfc793.txt) 76 | - IP 77 | - [INTERNET PROTOCOL](https://tools.ietf.org/html/rfc791) 78 | - [Internet Protocol, Version 6 (IPv6) Specification](https://www.ietf.org/rfc/rfc2460.txt) 79 | - Telnet 80 | - [TELNET PROTOCOL SPECIFICATION](https://www.ietf.org/rfc/rfc854.txt) 81 | - SSH 82 | - [The Secure Shell (SSH) Protocol Architecture](https://www.ietf.org/rfc/rfc4251.txt) 83 | - NAT 84 | - [The IP Network Address Translator (NAT)](https://www.ietf.org/rfc/rfc1631.txt) 85 | 86 | 87 | ## Courses 88 | 89 | - [Cisco Networking Academy Courses](https://www.netacad.com/courses/networking) - A various networking courses (Essentials, CCNA, CCNP, etc.). 90 | - [CBT Nuggets](https://www.cbtnuggets.com/) - An excelent place to start with the courses on various topics (Cisco, Juniper, CompTIA, etc.). 91 | - [ipSpace](https://www.ipspace.net/) - Contains excelent courses and webinars on various network topics, for both beginners and advanced people. 92 | - [GNS3 Academy](https://academy.gns3.com/) - A various number of courses related to the networking with GNS3 software. 93 | - [The Complete Networking Fundamentals Course](https://www.udemy.com/complete-networking-fundamentals-course-ccna-start/) - The most popular Networking Essentials course on Udemy. 94 | 95 | 96 | ## Tutorials 97 | 98 | - [Networking](https://www.youtube.com/watch?v=rL8RSFQG8do&list=PLF360ED1082F6F2A5) - A series of YouTube tutorials about networking by Eli the Computer Guy. 99 | - [Wireshark Tutorial for Beginners](https://www.youtube.com/watch?v=flDzURAm8wQ&list=PL6gx4Cwl9DGBI2ZFuyZOl5Q7sptR7PwYN) - TheNewBoston Wireshark Tutorial for Beginners. 100 | - [MikroTik WinBox Manual](https://wiki.mikrotik.com/wiki/Manual:Winbox) - The official manual for MikroTik's WinBox software. 101 | 102 | 103 | ## Books 104 | 105 | - [Computer Networking: A Top-Down Approach (7th Edition)](https://www.amazon.com/Computer-Networking-Top-Down-Approach-7th/dp/0133594149) - Excellent book for beginners (and advanced people) in networking. 106 | - [Internetworking with TCP/IP Volume One (6th Edition)](https://www.amazon.com/Internetworking-TCP-IP-One-6th/dp/013608530X) - A rich introduction book to the TCP/IP protocols and Internetworking. 107 | - [Network Security Essentials: Applications and Standards (6th Edition)](https://www.amazon.com/Network-Security-Essentials-Applications-Standards/dp/013452733X/) - A practical survey of network security applications and standards. 108 | - [Beej's Guide to Network Programming](https://beej.us/guide/bgnet/) - A free digital book about socket programming by Brian "Beej" Hall. 109 | - [Red Hat Enterprise Linux 7 Networking Guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/pdf/networking_guide/Red_Hat_Enterprise_Linux-7-Networking_Guide-en-US.pdf) - The official Red Hat's networking guide for Red Hat Enterprise Linux. 110 | - [Practical Packet Analysis (3rd Edition)](https://nostarch.com/packetanalysis3) - An amazing book about analyzing network packets using Wireshark. 111 | - [Attacking Network Protocols](https://nostarch.com/networkprotocols) - A Hacker's Guide to Capture, Analysis, and Exploitation 112 | by James Forshaw. 113 | - [Cisco Press](https://www.ciscopress.com/) - Cisco authorized book publisher where you can get all books and official guides for Cisco certifications. 114 | 115 | 116 | ## Software and Tools 117 | 118 | - [Wireshark](https://www.wireshark.org/) - The most popular free and open source network protocol analyzer. 119 | - [tcpdump](http://www.tcpdump.org/) - A powerful open source command-line packet analyzer. 120 | - [Nmap](https://nmap.org/) - A free and open source software for network discovery and security auditing. 121 | - [Zenmap](https://nmap.org/zenmap/) - The official Nmap Security Scanner GUI. 122 | - [GNS3](https://gns3.com/) - A powerful free and open source network simulator. 123 | - [Cisco Packet Tracer](https://www.netacad.com/courses/packet-tracer) - Cross-platform network visual simulation tool designed by Cisco Systems. 124 | - [pfSense](https://www.pfsense.org/) - An open source firewall/router computer software distribution based on FreeBSD. 125 | - [WinBox](https://mikrotik.com/download) - Official MikroTik GUI software for administration of MikroTik RouterOS. 126 | - [Online nslookup](https://www.nslookup.io) - An online DNS client to view and debug DNS configuration. 127 | - [Online whois](https://whois.domaintools.com/) - An online whois record tool for getting information about domains. 128 | - [OUI Lookup Tool](https://www.wireshark.org/tools/oui-lookup.html) - An online OUI lookup for searching vendors of MAC addresses. 129 | - [Draw.io](https://github.com/jgraph/drawio-desktop) - An open source software for creating network diagrams and topologies. 130 | 131 | ## Certifications 132 | 133 | - [Cisco certifications](https://www.cisco.com/c/en/us/training-events/training-certifications/certifications.html) 134 | - [MikroTik certified training programs](https://mikrotik.com/training/about) 135 | - [Juniper Certification Tracks](https://www.juniper.net/us/en/training/certification/certification-tracks/) 136 | - [CompTIA Network+](https://certification.comptia.org/certifications/network) 137 | 138 | 139 | ## Miscellaneous 140 | 141 | - [Network Analysis](https://github.com/briatte/awesome-network-analysis) - An awesome list of network analysis resources. 142 | - [Software Defined Networks (SDN)](https://github.com/sdnds-tw/awesome-sdn) - An awesome list about Software Defined Network (SDN). 143 | - [Reddit Networking](https://www.reddit.com/r/networking/) - Reddit group for networking. 144 | - [Network Engineering Stack Exchange](https://networkengineering.stackexchange.com/) - A question and answer site for network engineers. 145 | - [Server Fault](https://serverfault.com/) - A question and answer site for system and network administrators. 146 | 147 | ## Network Design Resources 148 | - [Cisco Design Zone](https://www.cisco.com/c/en/us/solutions/design-zone.html#~stickynav=1) 149 | - [Cumulus Networks Validated Design Guides](https://cumulusnetworks.com/learn/web-scale-networking-resources/?validated-design-guides) 150 | - [Juniper Solution Center](https://www.juniper.net/documentation/en_US/release-independent/solutions/information-products/pathway-pages/solutions/index.html) 151 | 152 | ## Network Implementation 153 | ### Routing 154 | - [Free Range Routing](https://frrouting.org/) - IP routing protocol suite for Linux and Unix platforms which 155 | includes protocol daemons for BGP, IS-IS, LDP, OSPF, PIM, and RIP. 156 | - [VyOS](https://vyos.io/) - Open source network operating system that can be installed on physical hardware or a virtual machine on your own server, or a cloud platform. 157 | 158 | ### SD-WAN 159 | - [Silver Peak](https://www.silver-peak.com/) - SD-WAN Solution(Commercial). 160 | ### Switching 161 | - [snabb](https://github.com/snabbco/snabb) - Snabb (formerly "Snabb Switch") is a simple and fast packet networking toolkit. 162 | 163 | ### VPN 164 | - [PiVPN](https://www.pivpn.io/) - Simplest OpenVPN setup and configuration, designed for Raspberry Pi. 165 | 166 | ### Network Services 167 | - [Pi-Hole](https://pi-hole.net/) - Network-wide ad blocking via your own Linux hardware. 168 | 169 | ### Network Simulators and Traffic Generators 170 | - [GNS3](https://www.gns3.com/) - Network software emulator that allows the combination of virtual and real devices, used to simulate complex networks. 171 | - [Mininet](http://mininet.org/) - Instant Virtual Network on your Laptop. 172 | - [WANem](http://wanem.sourceforge.net/) - Wide Area Network Emulator. 173 | - [Ostinato](https://ostinato.org/) - Packet crafter, network traffic generator and analyzer with a friendly GUI. 174 | - [SIPp](http://sipp.sourceforge.net/index.html) - Free Open Source test tool / traffic generator for the SIP protocol. 175 | - [StarTrinity SIP Tester™](https://startrinity.com/VoIP/SipTester/SipTester.aspx) - VoIP monitoring and testing tool, VoIP recorder. 176 | - [Multi-Generator](https://github.com/USNavalResearchLaboratory/mgen) - Open source software that provides the ability to perform IP network performance tests and measurements using TCP and UDP/IP traffic. 177 | - [Network-Conditions-Emulator](https://github.com/marty90/Network-Conditions-Emulator) - Artificially limit uplink and downlink bandwidth, delay and loss rate on selected interfaces. 178 | - [snabb](https://github.com/snabbco/snabb) - Snabb (formerly "Snabb Switch") is a simple and fast packet networking toolkit. 179 | - [vqfx10k-vagrant](https://github.com/juniper/vqfx10k-vagrant) - Vagrant files to bring up Juniper virtual QFX instances 180 | - [Packet Communication Investigator](https://github.com/michoo/pci) - import network traffic into a graphtool to analyse packet interactions between machines and network 181 | - [SafePcap](https://omnipacket.com/safepcap) - GDPR and NISTIR 8053 Compliance for your Pcap files 182 | - [Arkime](https://github.com/arkime/arkime) - Arkime augments your current security infrastructure to store and index network traffic in standard PCAP format, providing fast, indexed access 183 | - [pyNTM](https://pyntm.readthedocs.io/en/latest/index.html) - a network traffic modeler written in python 3. 184 | 185 | ## Network Operations 186 | ### Network Change Management 187 | - [Batfish](https://github.com/batfish/batfish) - Network configuration analysis tool that can find bugs and guarantee the correctness of (planned or current) network configurations. 188 | - [Oxidized](https://github.com/ytti/oxidized) - Network device configuration backup tool. It's a [RANCID](https://www.shrubbery.net/rancid/) replacement. 189 | - [Netshot](http://www.netfishers.onl/netshot) - Network configuration and compliance management software. 190 | - [Jazigo](https://github.com/udhos/jazigo) - Jazigo is a tool written in Go for retrieving configuration for multiple devices, similar to rancid, fetchconfig, oxidized, Sweet. 191 | - [fetchconfig](https://github.com/udhos/fetchconfig) - fetchconfig is a Perl script for retrieving configuration of 192 | multiple devices 193 | - [sweet](https://github.com/AppliedTrust/sweet) - Network device configuration backups and change alerts for the 21st century - inspired by RANCID! 194 | - [stockpiler](https://github.com/lykinsbd/stockpiler) - Stockpiler gathers network device configurations and stores them in a local Git repository. 195 | 196 | ## Network Automation 197 | - [Napalm](https://napalm-automation.net/) - Vendor neutral, cross-platform open source project that provides a unified API to network devices. 198 | - [netmiko](https://github.com/ktbyers/netmiko) - Multi-vendor library to simplify Paramiko SSH connections to network devices. 199 | - [trigger](https://github.com/trigger/trigger) - Robust network automation toolkit written in Python that was designed for interfacing with network devices. 200 | - [Ansible](https://github.com/ansible/ansible) - IT automation platform that makes your applications and systems easier to deploy by using SSH, with no agents to install on remote systems. 201 | - [nornir](https://github.com/nornir-automation/nornir) - Pluggable multi-threaded framework with inventory management to help operate collections of devices 202 | - [CNaaS-NMS](https://github.com/SUNET/cnaas-nms) - Campus Network-as-a-Service - Network Management System. Software to automate management of a campus network (LAN). 203 | - [pyats](https://developer.cisco.com/pyats/) - pyATS enable network engineers to perform stateful validation of their device operational status 204 | - [itential.com](https://www.itential.com/) - ow-Code Automation for Physical, Virtual, and Cloud Networks(commercial) 205 | - [AWX](https://github.com/ansible/awx) - the upstream project for Tower, a commercial derivative of AWX. 206 | - [Unimus](https://unimus.net/) Unimus makes Network Automation and Configuration Management easy (commercial) 207 | 208 | ## Network Monitoring 209 | - [perfSONAR](https://www.perfsonar.net) - Network measurement toolkit designed to provide federated coverage of paths, and help to establish end-to-end usage expectations. 210 | - [UDPing](https://github.com/yahoo/UDPing) - Measure latency and packet loss across a link. 211 | - [Vaping](https://github.com/20c/vaping) - vaping is a healthy alternative to smokeping! 212 | - [veryflow](https://www.veriflow.net/) - Continuous network verification system. 213 | - [Forward Networks](https://www.forwardnetworks.com/) - Network Behavior Analysis (Commercial). 214 | - [ToDD](https://github.com/toddproject/todd) - Distributed, testing-on-demand system focused on testing network related conditions. 215 | - [pmacct](http://www.pmacct.net/) - Small set of multi-purpose passive network monitoring tools, including Netflow or IPFIX generation. 216 | - [LibreNMS](https://www.librenms.org/) - Network monitoring system that supports automatic discovery, alerting, distributed polling and others. 217 | - [Observium](https://observium.org/) - Low-maintenance auto-discovering network monitoring platform. 218 | - [Elastiflow](https://github.com/robcowart/elastiflow) - Netflow collector and reporting 219 | 220 | ## Security Monitoring 221 | - [cPacket](https://www.cpacket.com) - Performance monitoring solutions that deliver real-time analysis and coverage (Commercial). 222 | - [Proxmox Mail Gateway](https://www.proxmox.com/en/proxmox-mail-gateway) - Open-source email security solution helping you to protect your mail server against all email threats the moment they emerge. 223 | - [FastNetMon](https://fastnetmon.com/) - DDoS detection tool (Open Source or Commercial). 224 | - [PyREBox](https://github.com/Cisco-Talos/pyrebox) - Python scriptable Reverse Engineering Sandbox, a Virtual Machine instrumentation and inspection framework based on QEMU 225 | - [Canary](https://canary.tools/) - Honeypot solution (commercial) 226 | - [CanaryTokens](https://canarytokens.org/generate) - Free honeytoken 227 | - [Malcolm](https://github.com/idaholab/Malcolm) - Malcolm is a powerful, easily deployable network traffic analysis tool suite for full packet capture artifacts (PCAP files) and Zeek logs. 228 | - [Zeek](https://zeek.org/) - Zeek is an open source network security monitoring tool. 229 | - [zeek2es](https://github.com/corelight/zeek2es) - A Zeek log to Elastic/OpenSearch log converter. 230 | 231 | ## Network Inventory 232 | - [phpipam](https://phpipam.net/) - Open-source web IP address management application (IPAM). 233 | - [nsot](https://github.com/dropbox/nsot) - Network Source of Truth is an open source IPAM and network inventory database. 234 | - [netbox](https://github.com/digitalocean/netbox) - IP address management (IPAM) and data center infrastructure management (DCIM) tool. 235 | - [ipfabric](https://ipfabric.io/product/network-mapping) - Network Topology Mapping & Visualization (Commercial) 236 | - [drawthe.net](https://github.com/cidrblock/drawthe.net) - Draws network diagrams dynamically from a text file describing the placement, layout and icons. 237 | 238 | ## Networking Labs 239 | - [VIRL](https://learningnetworkstore.cisco.com/virlfaq) - Virtual Internet Routing Lab by Cisco 240 | - [dCloud](https://dcloud.cisco.com/) - Fully scripted, customizable environments available almost instantly in the cloud for free 241 | - [Cisco DevNet Labs](https://developer.cisco.com/site/sandbox/) - https://developer.cisco.com/site/sandbox/ 242 | 243 | # Related resources 244 | ## DevNet Tools 245 | - [Celery](http://www.celeryproject.org/) - Asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation, but supports scheduling as well. 246 | - [Ajenti](https://ajenti.org/) - Manage a remote Linux box at any time using everyday tools like a web terminal, text editor, file manager and others. 247 | - [ProxMox Virtualiation Platform](https://www.proxmox.com/en/proxmox-ve) - Open-source platform for enterprise virtualization that tightly integrates KVM hypervisor and LXC containers, software-defined storage and networking functionality on a single platform, and easily manages high availability clusters and disaster recovery tools with the built-in web management interface. 248 | - [ops_tcpdump_handler](https://github.com/cerner/ops_tcpdump_handler) - Chef Cookbook to test network connectivity 249 | - [chromaterm](https://github.com/hSaria/ChromaTerm) - ChromaTerm is a Python module and script used for coloring the output to terminals 250 | - [telnetmyip.com](https://telnetmyip.com/) - Simple service that returns your source IP information in a json format 251 | - [icanhaztraceroute.com](https://icanhaztraceroute.com/) - Simple service that returns a traceroute back to your source IP 252 | - [Who is my ISP?](https://www.whoismyisp.org) - Simple service that shows the ISP of an IP 253 | - [NsLookup.io](https://www.nslookup.io) - Simple service that shows all DNS records for a domain name 254 | - [netshoot](https://github.com/nicolaka/netshoot) - a Docker + Kubernetes network trouble-shooting swiss-army container 255 | 256 | ## DevNet Monitoring 257 | - [netdata](https://github.com/firehol/netdata) - Distributed real-time performance and health monitoring. 258 | - [Grafana](https://grafana.com/) - Open source software for time series analytics. 259 | - [monit](https://mmonit.com/monit/) -Small Open Source utility for managing and monitoring Unix systems. Monit conducts automatic maintnance and repair and can execute meaningful causal actions in error situations. 260 | - [Prometheus](https://prometheus.io/) - Open-source systems monitoring and alerting toolkit originally built at SoundCloud. 261 | - [sensu](https://sensuapp.org/) - Monitor servers, services, application health, and business KPIs. Collect and analyze custom metrics. Get notified about failures before your users do. Give your business the competitive advantage it deserves. (Open Source or Commercial) 262 | - ELK Stack 263 | - [Elasticsearch](https://github.com/elastic/elasticsearch) - Open Source, Distributed, RESTful Search Engine. 264 | - [LogStash](https://github.com/elastic/logstash) - Transport and process your logs, events, or other data. 265 | - [Kibana](https://github.com/elastic/kibana) - Analytics and search dashboard for Elasticsearch. 266 | - [Graylog](https://www.graylog.org/) - Parse and enrich logs, wire data, and event data from any data source (Commercial, Free for less than 5GB/day). 267 | 268 | ### DevNet Knowledgebase 269 | - [ITGlue](https://www.itglue.com/) - IT focused documentation solution (Commercial). 270 | 271 | ### DevNet Inventory 272 | - [Snipe IT](https://snipeitapp.com/) - Open Source Asset Management tool. 273 | 274 | ### Knowledge Resources 275 | - [Packet Pushers Podcast](https://packetpushers.net/) - Podcast about data networking by network architects. Deeply technical & unabashedly nerdy. 276 | - [Risky Business Podcast](https://risky.biz/) - Features news and in-depth commentary from security industry luminaries. 277 | - [Software Gone Wild Podcast](https://www.ipspace.net/Podcast/Software_Gone_Wild/) - Software Gone Wild is focusing on architectures, solutions and technologies that real networking engineers use in production networks 278 | - [Cisco DevNet Basics](https://developer.cisco.com/video/net-prog-basics) - Learn network programmability basics 279 | - [Cisco Tools](https://www.cisco.com/c/en/us/support/web/tools-catalog.html) - List of Cisco tools maintained by Cisco 280 | 281 | 282 | 283 | ## `License` 284 | MIT License & [cc](https://creativecommons.org/licenses/by/4.0/) license 285 | 286 | Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. 287 | 288 | To the extent possible under law, [Paul Veillard](https://github.com/paulveillard/) has waived all copyright and related or neighboring rights to this work. 289 | 290 | **[`^ back to top ^`](#)** 291 | 292 | 293 | 294 | 295 | 296 | 297 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | 4 | ## Our Pledge 5 | 6 | In the interest of fostering an open and welcoming environment, we as 7 | contributors and maintainers pledge to making participation in our project and 8 | our community a harassment-free experience for everyone, regardless of age, body 9 | size, disability, ethnicity, gender identity and expression, level of experience, 10 | nationality, personal appearance, race, religion, or sexual identity and 11 | orientation. 12 | 13 | ## Our Standards 14 | 15 | Examples of behavior that contributes to creating a positive environment 16 | include: 17 | 18 | * Using welcoming and inclusive language 19 | * Being respectful of differing viewpoints and experiences 20 | * Gracefully accepting constructive criticism 21 | * Focusing on what is best for the community 22 | * Showing empathy towards other community members 23 | 24 | Examples of unacceptable behavior by participants include: 25 | 26 | * The use of sexualized language or imagery and unwelcome sexual attention or 27 | advances 28 | * Trolling, insulting/derogatory comments, and personal or political attacks 29 | * Public or private harassment 30 | * Publishing others' private information, such as a physical or electronic 31 | address, without explicit permission 32 | * Other conduct which could reasonably be considered inappropriate in a 33 | professional setting 34 | 35 | ## Our Responsibilities 36 | 37 | Project maintainers are responsible for clarifying the standards of acceptable 38 | behavior and are expected to take appropriate and fair corrective action in 39 | response to any instances of unacceptable behavior. 40 | 41 | Project maintainers have the right and responsibility to remove, edit, or 42 | reject comments, commits, code, wiki edits, issues, and other contributions 43 | that are not aligned to this Code of Conduct, or to ban temporarily or 44 | permanently any contributor for other behaviors that they deem inappropriate, 45 | threatening, offensive, or harmful. 46 | 47 | ## Scope 48 | 49 | This Code of Conduct applies both within project spaces and in public spaces 50 | when an individual is representing the project or its community. Examples of 51 | representing a project or community include using an official project e-mail 52 | address, posting via an official social media account, or acting as an appointed 53 | representative at an online or offline event. Representation of a project may be 54 | further defined and clarified by project maintainers. 55 | 56 | ## Enforcement 57 | 58 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 59 | reported by contacting the project team at management@paulveillard.com. All 60 | complaints will be reviewed and investigated and will result in a response that 61 | is deemed necessary and appropriate to the circumstances. The project team is 62 | obligated to maintain confidentiality with regard to the reporter of an incident. 63 | Further details of specific enforcement policies may be posted separately. 64 | 65 | Project maintainers who do not follow or enforce the Code of Conduct in good 66 | faith may face temporary or permanent repercussions as determined by other 67 | members of the project's leadership. 68 | 69 | ## Attribution 70 | 71 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 72 | available at [http://contributor-covenant.org/version/1/4][version] 73 | 74 | [homepage]: http://contributor-covenant.org 75 | [version]: http://contributor-covenant.org/version/1/4/ 76 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contribution 2 | 3 | This project welcomes contributions from the community. All contributions to this repository must be 4 | signed as described on that page. Your signature certifies that you wrote the patch or have the right to pass it on 5 | as an open-source patch. 6 | 7 | ## Contribution Flow 8 | 9 | This is a rough outline of what a contributor's workflow looks like: 10 | 11 | - Create a topic branch from where you want to base your work 12 | - Make commits of logical units 13 | - Make sure your commit messages are in the proper format (see below) 14 | - Push your changes to a topic branch in your fork of the repository 15 | - Submit a pull request 16 | 17 | Example: 18 | 19 | ``` shell 20 | git remote add upstream https://github.com/paulveillard/ 21 | git checkout -b my-new-feature master 22 | git commit -a 23 | git push origin my-new-feature 24 | ``` 25 | 26 | ### Staying In Sync With Upstream 27 | 28 | When your branch gets out of sync with the paulveillard/master branch, use the following to update: 29 | 30 | ``` shell 31 | git checkout my-new-feature 32 | git fetch -a 33 | git pull --rebase upstream master 34 | git push --force-with-lease origin my-new-feature 35 | ``` 36 | 37 | ### Updating pull requests 38 | 39 | If your PR fails to pass CI or needs changes based on code review, you'll most likely want to squash these changes into 40 | existing commits. 41 | 42 | If your pull request contains a single commit or your changes are related to the most recent commit, you can simply 43 | amend the commit. 44 | 45 | ``` shell 46 | git add . 47 | git commit --amend 48 | git push --force-with-lease origin my-new-feature 49 | ``` 50 | 51 | If you need to squash changes into an earlier commit, you can use: 52 | 53 | ``` shell 54 | git add . 55 | git commit --fixup 56 | git rebase -i --autosquash master 57 | git push --force-with-lease origin my-new-feature 58 | ``` 59 | 60 | Be sure to add a comment to the PR indicating your new changes are ready to review, as GitHub does not generate a 61 | notification when you git push. 62 | 63 | ### Code Style 64 | 65 | ### Formatting Commit Messages 66 | 67 | We follow the conventions on [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/). 68 | 69 | Be sure to include any related GitHub issue references in the commit message. See 70 | [GFM syntax](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown) for referencing issues 71 | and commits. 72 | 73 | ## Reporting Bugs and Creating Issues 74 | 75 | When opening a new issue, try to roughly follow the commit message format conventions above. 76 | -------------------------------------------------------------------------------- /img/625x403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/625x403.png -------------------------------------------------------------------------------- /img/cloud1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/cloud1.png -------------------------------------------------------------------------------- /img/dhcp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/dhcp.png -------------------------------------------------------------------------------- /img/dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/dns.png -------------------------------------------------------------------------------- /img/ftp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/ftp.png -------------------------------------------------------------------------------- /img/network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paulveillard/cybersecurity-networking/6d5f6f127d29329c716a10df1a0b390ed0610e29/img/network.png -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Roger Perkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/README.md: -------------------------------------------------------------------------------- 1 | # Python Scripts for Network Engineers 2 | Python Scripts for Network Engineers is a collection of scripts that I use every day as a network engineer to make my life easier. 3 | 4 | https://www.rogerperkin.co.uk/network-automation/python/scripts-for-network-engineers/ 5 | 6 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/backup-multiple-routers.py: -------------------------------------------------------------------------------- 1 | # SSH to Multiple Devices from devices file 2 | from netmiko import ConnectHandler 3 | 4 | with open('devices.txt') as routers: 5 | for IP in routers: 6 | Router = { 7 | 'device_type': 'cisco_ios', 8 | 'ip': IP, 9 | 'username': 'roger', 10 | 'password': 'cisco' 11 | } 12 | 13 | net_connect = ConnectHandler(**Router) 14 | 15 | hostname = net_connect.send_command('show run | i host') 16 | hostname.split(" ") 17 | hostname,device = hostname.split(" ") 18 | print ("Backing up " + device) 19 | 20 | filename = '/home/roger/python-scripts-for-network-engineers/backups/' + device + '.txt' 21 | # to save backup to same folder as script use below line and comment out above line 22 | # filename = device + '.txt' 23 | 24 | showrun = net_connect.send_command('show run') 25 | showvlan = net_connect.send_command('show vlan') 26 | showver = net_connect.send_command('show ver') 27 | log_file = open(filename, "a") # in append mode 28 | log_file.write(showrun) 29 | log_file.write("\n") 30 | log_file.write(showvlan) 31 | log_file.write("\n") 32 | log_file.write(showver) 33 | log_file.write("\n") 34 | 35 | # Finally close the connection 36 | net_connect.disconnect() 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/backup-router.py: -------------------------------------------------------------------------------- 1 | from netmiko import ConnectHandler 2 | 3 | #First create the device object using a dictionary 4 | CSR = { 5 | 'device_type': 'cisco_ios', 6 | 'ip': '192.168.1.220', 7 | 'username': 'roger', 8 | 'password': 'cisco' 9 | } 10 | 11 | # Next establish the SSH connection 12 | net_connect = ConnectHandler(**CSR) 13 | 14 | #Discover the hostname from the prompt 15 | 16 | hostname = net_connect.send_command('show run | i host') 17 | hostname.split(" ") 18 | hostname,device = hostname.split(" ") 19 | print ("Backing up " + device) 20 | 21 | filename = '/home/roger/python-scripts-for-network-engineers/backups/' + device + '.txt' 22 | # to save backup to same folder as script use below line and comment out above line 23 | # filename = device + '.txt' 24 | 25 | showrun = net_connect.send_command('show run') 26 | showvlan = net_connect.send_command('show vlan') 27 | showver = net_connect.send_command('show ver') 28 | log_file = open(filename, "a") # in append mode 29 | log_file.write(showrun) 30 | log_file.write("\n") 31 | log_file.write(showvlan) 32 | log_file.write("\n") 33 | log_file.write(showver) 34 | log_file.write("\n") 35 | 36 | # Finally close the connection 37 | net_connect.disconnect() 38 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/device-types.py: -------------------------------------------------------------------------------- 1 | # Simple script to show all the device types available with Netmiko 2 | 3 | from netmiko import ConnectHandler 4 | 5 | # Just pick an 'invalid' device_type 6 | cisco1 = { 7 | "device_type": "invalid", 8 | "host": "cisco1.lasthop.io", 9 | "username": "pyclass", 10 | "password": "invalid" 11 | } 12 | 13 | net_connect = ConnectHandler(**cisco1) 14 | net_connect.disconnect() -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/devices.txt: -------------------------------------------------------------------------------- 1 | 192.168.1.220 2 | 192.168.1.221 3 | 192.168.1.222 4 | 192.168.1.223 5 | 192.168.1.224 -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/netmiko-save-config.py: -------------------------------------------------------------------------------- 1 | from netmiko import ConnectHandler 2 | from getpass import getpass 3 | 4 | username = input('Username: ') 5 | password = getpass() 6 | 7 | CSR = { 8 | 'device_type': 'cisco_ios', 9 | 'ip': '192.168.1.220', 10 | 'password': password, 11 | 'username': username 12 | } 13 | 14 | net_connect = ConnectHandler(**CSR) 15 | 16 | print('-'*79) 17 | print('Saving Config ') 18 | print('-'*79) 19 | 20 | output = net_connect.save_config() 21 | print(output) 22 | 23 | print('-'*79) 24 | print('Config Saved ') 25 | print('-'*79) 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/ping-trace.py: -------------------------------------------------------------------------------- 1 | import os 2 | from concurrent.futures import ThreadPoolExecutor 3 | from subprocess import check_output, CalledProcessError 4 | import logging 5 | import sys 6 | import time 7 | 8 | CURRENT_DIR = os.getcwd() 9 | START_TIME = time.time() 10 | MAX_THREADS = 5 11 | FILENAME = 'devices.txt' 12 | PING_COMMAND = 'ping -q -c 3 -W 1' 13 | TRACEROUTE_COMMAND = 'traceroute' 14 | 15 | formatter = '%(asctime)s - %(levelname)s - %(message)s' 16 | logging.basicConfig(stream=sys.stdout, format=formatter, level=logging.DEBUG) 17 | 18 | 19 | def title(section_name): 20 | section_title = '\n' + '*' * 70 + f'\n{section_name}\n' + '*' * 70 + '\n' 21 | 22 | return section_title 23 | 24 | 25 | def health_checks(ip): 26 | ping_cmd = f'{PING_COMMAND} {ip}' 27 | trace_cmd = f'{TRACEROUTE_COMMAND} {ip}' 28 | 29 | ping_status = run_command(ping_cmd) 30 | trace_status = run_command(trace_cmd) 31 | 32 | filename = f'{CURRENT_DIR}{os.sep}{ip}.txt' 33 | with open(filename, 'w') as f: 34 | f.write(title('Ping Results:')) 35 | f.write(ping_status) 36 | 37 | f.write(title('Trace Results:')) 38 | f.write(trace_status) 39 | 40 | logging.info(f'Wrote outputs to: {filename}') 41 | logging.debug(ping_status) 42 | logging.debug(trace_status) 43 | 44 | 45 | def run_command(command): 46 | logging.info(f'running: {command}') 47 | 48 | split_cmd = command.split() 49 | 50 | try: 51 | output = check_output(split_cmd).decode('utf-8') 52 | 53 | except CalledProcessError: 54 | return 'FAILED' 55 | 56 | return output 57 | 58 | 59 | def main(): 60 | with open(FILENAME, 'r') as f: 61 | ips = f.read().splitlines() 62 | num_ips = len(ips) 63 | 64 | with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor: 65 | [executor.submit(health_checks, ip) for ip in ips] 66 | 67 | end_time = time.time() - START_TIME 68 | logging.info(f'Checked {num_ips} hosts in {round(end_time)} seconds.') 69 | 70 | 71 | if __name__ == '__main__': 72 | main() -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/ping.py: -------------------------------------------------------------------------------- 1 | from subprocess import check_output, CalledProcessError 2 | 3 | FILENAME = 'ips.txt' 4 | PING_COMMAND = 'ping -q -c 3 -W 1' 5 | 6 | 7 | def ping(ip): 8 | cmd = f'{PING_COMMAND} {ip}' 9 | split_cmd = cmd.split() 10 | 11 | print(f'running: {cmd}') 12 | 13 | try: 14 | check_output(split_cmd) 15 | 16 | except CalledProcessError: 17 | print(f'{ip} is UNREACHABLE!') 18 | 19 | return 20 | 21 | print(f'{ip} is reachable') 22 | 23 | 24 | def main(): 25 | with open(FILENAME, 'r') as f: 26 | ips = f.read().splitlines() 27 | 28 | for ip in ips: 29 | ping(ip) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/ssh-to-multiple-routers.py: -------------------------------------------------------------------------------- 1 | # SSH to Multiple Devices from devices file 2 | from netmiko import ConnectHandler 3 | 4 | with open('devices.txt') as routers: 5 | for IP in routers: 6 | Router = { 7 | 'device_type': 'cisco_ios', 8 | 'ip': IP, 9 | 'username': 'roger', 10 | 'password': 'cisco' 11 | } 12 | 13 | net_connect = ConnectHandler(**Router) 14 | 15 | print ('Connecting to ' + IP) 16 | print('-'*79) 17 | output = net_connect.send_command('sh ip int brief') 18 | print(output) 19 | print() 20 | print('-'*79) 21 | 22 | # Finally close the connection 23 | net_connect.disconnect() 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /python-scripts-for-network-engineers/ssh-to-router.py: -------------------------------------------------------------------------------- 1 | from netmiko import ConnectHandler 2 | 3 | #First create the device object using a dictionary 4 | CSR = { 5 | 'device_type': 'cisco_ios', 6 | 'ip': '192.168.1.220', 7 | 'username': 'roger', 8 | 'password': 'cisco' 9 | } 10 | 11 | # Next establish the SSH connection 12 | net_connect = ConnectHandler(**CSR) 13 | 14 | # Then send the command and print the output 15 | output = net_connect.send_command('show ip int brief') 16 | print (output) 17 | 18 | # Finally close the connection 19 | net_connect.disconnect() 20 | --------------------------------------------------------------------------------