├── CircularBuffer ├── CircularBuffer.c ├── CircularBuffer.h ├── Makefile ├── README.md └── main.c ├── HashTable ├── HashTable.c ├── HashTable.h ├── README.md ├── main.c └── makefile ├── HelloWorld └── main.c ├── List ├── List.c ├── List.h ├── ListItem.c ├── ListItem.h ├── Makefile ├── README.md └── main.c ├── Queue ├── Makefile ├── Queue.c ├── Queue.h ├── README.md └── main.c ├── README.md ├── input_output └── main.c ├── pointers └── main.c └── vpn ├── Makefile ├── README.md ├── configure.sh ├── minivpn └── minivpn.c /CircularBuffer/CircularBuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/6/13 4 | */ 5 | 6 | #include 7 | 8 | #include "CircularBuffer.h" 9 | 10 | CircularBuffer * circularbuffer_initialize(size_t size, void * val){ 11 | size_t i; 12 | CircularBuffer * cb = (CircularBuffer *)malloc( sizeof(CircularBuffer) ); 13 | 14 | if (cb == NULL) { 15 | 16 | // any other implementation may be added here. 17 | 18 | printf("\nERROR: Insufficient memory. Terminating..."); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | cb->buffer = (Item *)calloc(size, sizeof(Item)); 23 | 24 | if (cb->buffer == NULL) { 25 | 26 | // any other implementation may be added here. 27 | 28 | printf("\nERROR: Insufficient memory. Terminating..."); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | for(i=0; ibuffer[i].data = val; 34 | } 35 | 36 | cb->size = size; 37 | cb->start = 0; 38 | cb->end = 0; 39 | 40 | return(cb); 41 | } 42 | 43 | int circularbuffer_add(CircularBuffer * cb, void * val){ 44 | cb->buffer[ cb->end ].data = val; 45 | cb->end = (cb->end + 1) % cb->size; 46 | 47 | if( cb->end == cb->start){ 48 | cb->start = (cb->start + 1) % cb->size; 49 | } 50 | 51 | return(1); 52 | } 53 | 54 | void * circularbuffer_read(CircularBuffer * cb){ 55 | size_t start = cb->start; 56 | cb->start = (cb->start + 1) % cb->size; 57 | 58 | return( cb->buffer[ start ].data ); 59 | } 60 | 61 | int circularbuffer_destroy(CircularBuffer * cb, circularbuffer_destroybuffer df){ 62 | size_t i; 63 | 64 | for(i=0; isize; i++){ 65 | df( cb->buffer[i].data ); 66 | } 67 | 68 | free(cb->buffer); 69 | return(1); 70 | } 71 | -------------------------------------------------------------------------------- /CircularBuffer/CircularBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/6/13 4 | * 5 | * LIFO, in this case, easily 6 | * could be FIFO. But this is 7 | * traditionally a LIFO. 8 | */ 9 | 10 | #ifndef __CIRCULARBUFFER_H__ 11 | #define __CIRCULARBUFFER_H__ 12 | 13 | typedef void (* circularbuffer_destroybuffer)(void *); 14 | 15 | typedef struct Item{ 16 | void * data; 17 | } Item; 18 | 19 | typedef struct CircularBuffer{ 20 | size_t size; 21 | size_t start; 22 | size_t end; 23 | Item * buffer; 24 | } CircularBuffer; 25 | 26 | /* 27 | * Returns initialized CircularBuffer instance of 28 | * size size_t and all items initialized to second 29 | * parameter. 30 | */ 31 | CircularBuffer * circularbuffer_initialize(size_t, void *); 32 | 33 | /* 34 | * Overwrites oldest item in the buffer. 35 | */ 36 | int circularbuffer_add(CircularBuffer *, void *); 37 | 38 | /* 39 | * Returns oldeset item in the buffer. 40 | */ 41 | void * circularbuffer_read(CircularBuffer *); 42 | 43 | /* 44 | * Destroys buffer entirely. 45 | */ 46 | int circularbuffer_destroy(CircularBuffer *, circularbuffer_destroybuffer); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /CircularBuffer/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # 3 | # Generic Makefile for C/C++ Program 4 | # 5 | # License: GPL (General Public License) 6 | # Author: whyglinux 7 | # Date: 2006/03/04 (version 0.1) 8 | # 2007/03/24 (version 0.2) 9 | # 2007/04/09 (version 0.3) 10 | # 2007/06/26 (version 0.4) 11 | # 2008/04/05 (version 0.5) 12 | # 13 | # Description: 14 | # ------------ 15 | # This is an easily customizable makefile template. The purpose is to 16 | # provide an instant building environment for C/C++ programs. 17 | # 18 | # It searches all the C/C++ source files in the specified directories, 19 | # makes dependencies, compiles and links to form an executable. 20 | # 21 | # Besides its default ability to build C/C++ programs which use only 22 | # standard C/C++ libraries, you can customize the Makefile to build 23 | # those using other libraries. Once done, without any changes you can 24 | # then build programs using the same or less libraries, even if source 25 | # files are renamed, added or removed. Therefore, it is particularly 26 | # convenient to use it to build codes for experimental or study use. 27 | # 28 | # GNU make is expected to use the Makefile. Other versions of makes 29 | # may or may not work. 30 | # 31 | # Usage: 32 | # ------ 33 | # 1. Copy the Makefile to your program directory. 34 | # 2. Customize in the "Customizable Section" only if necessary: 35 | # * to use non-standard C/C++ libraries, set pre-processor or compiler 36 | # options to and linker ones to 37 | # (See Makefile.gtk+-2.0 for an example) 38 | # * to search sources in more directories, set to 39 | # * to specify your favorite program name, set to 40 | # 3. Type make to start building your program. 41 | # 42 | # Make Target: 43 | # ------------ 44 | # The Makefile provides the following targets to make: 45 | # $ make compile and link 46 | # $ make NODEP=yes compile and link without generating dependencies 47 | # $ make objs compile only (no linking) 48 | # $ make tags create tags for Emacs editor 49 | # $ make ctags create ctags for VI editor 50 | # $ make clean clean objects and the executable file 51 | # $ make distclean clean objects, the executable and dependencies 52 | # $ make help get the usage of the makefile 53 | # 54 | #=========================================================================== 55 | 56 | ## Customizable Section: adapt those variables to suit your program. 57 | ##========================================================================== 58 | 59 | # The pre-processor and compiler options. 60 | MY_CFLAGS = 61 | 62 | # The linker options. 63 | MY_LIBS = 64 | 65 | # The pre-processor options used by the cpp (man cpp for more). 66 | CPPFLAGS = -Wall 67 | 68 | # The options used in linking as well as in any direct use of ld. 69 | LDFLAGS = 70 | 71 | # The directories in which source files reside. 72 | # If not specified, only the current directory will be searched. 73 | SRCDIRS = 74 | 75 | # The executable file name. 76 | # If not specified, current directory name or `a.out' will be used. 77 | PROGRAM = main 78 | 79 | ## Implicit Section: change the following only when necessary. 80 | ##========================================================================== 81 | 82 | # The source file types (headers excluded). 83 | # .c indicates C source files, and others C++ ones. 84 | SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp 85 | 86 | # The header file types. 87 | HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp 88 | 89 | # The pre-processor and compiler options. 90 | # Users can override those variables from the command line. 91 | CFLAGS = -g -O2 92 | CXXFLAGS= -g -O2 93 | 94 | # The C program compiler. 95 | CC = gcc 96 | 97 | # The C++ program compiler. 98 | #CXX = g++ 99 | 100 | # Un-comment the following line to compile C programs as C++ ones. 101 | #CC = $(CXX) 102 | 103 | # The command used to delete file. 104 | #RM = rm -f 105 | 106 | ETAGS = etags 107 | ETAGSFLAGS = 108 | 109 | CTAGS = ctags 110 | CTAGSFLAGS = 111 | 112 | ## Stable Section: usually no need to be changed. But you can add more. 113 | ##========================================================================== 114 | SHELL = /bin/sh 115 | EMPTY = 116 | SPACE = $(EMPTY) $(EMPTY) 117 | ifeq ($(PROGRAM),) 118 | CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))) 119 | PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES)) 120 | ifeq ($(PROGRAM),) 121 | PROGRAM = a.out 122 | endif 123 | endif 124 | ifeq ($(SRCDIRS),) 125 | SRCDIRS = . 126 | endif 127 | SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) 128 | HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS)))) 129 | SRC_CXX = $(filter-out %.c,$(SOURCES)) 130 | OBJS = $(addsuffix .o, $(basename $(SOURCES))) 131 | DEPS = $(OBJS:.o=.d) 132 | 133 | ## Define some useful variables. 134 | DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \ 135 | echo "-MM -MP"; else echo "-M"; fi ) 136 | DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) 137 | DEPEND.d = $(subst -g ,,$(DEPEND)) 138 | COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c 139 | COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c 140 | LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 141 | LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) 142 | 143 | .PHONY: all objs tags ctags clean distclean help show 144 | 145 | # Delete the default suffixes 146 | .SUFFIXES: 147 | 148 | all: $(PROGRAM) 149 | 150 | # Rules for creating dependency files (.d). 151 | #------------------------------------------ 152 | 153 | %.d:%.c 154 | @echo -n $(dir $<) > $@ 155 | @$(DEPEND.d) $< >> $@ 156 | 157 | %.d:%.C 158 | @echo -n $(dir $<) > $@ 159 | @$(DEPEND.d) $< >> $@ 160 | 161 | %.d:%.cc 162 | @echo -n $(dir $<) > $@ 163 | @$(DEPEND.d) $< >> $@ 164 | 165 | %.d:%.cpp 166 | @echo -n $(dir $<) > $@ 167 | @$(DEPEND.d) $< >> $@ 168 | 169 | %.d:%.CPP 170 | @echo -n $(dir $<) > $@ 171 | @$(DEPEND.d) $< >> $@ 172 | 173 | %.d:%.c++ 174 | @echo -n $(dir $<) > $@ 175 | @$(DEPEND.d) $< >> $@ 176 | 177 | %.d:%.cp 178 | @echo -n $(dir $<) > $@ 179 | @$(DEPEND.d) $< >> $@ 180 | 181 | %.d:%.cxx 182 | @echo -n $(dir $<) > $@ 183 | @$(DEPEND.d) $< >> $@ 184 | 185 | # Rules for generating object files (.o). 186 | #---------------------------------------- 187 | objs:$(OBJS) 188 | 189 | %.o:%.c 190 | $(COMPILE.c) $< -o $@ 191 | 192 | %.o:%.C 193 | $(COMPILE.cxx) $< -o $@ 194 | 195 | %.o:%.cc 196 | $(COMPILE.cxx) $< -o $@ 197 | 198 | %.o:%.cpp 199 | $(COMPILE.cxx) $< -o $@ 200 | 201 | %.o:%.CPP 202 | $(COMPILE.cxx) $< -o $@ 203 | 204 | %.o:%.c++ 205 | $(COMPILE.cxx) $< -o $@ 206 | 207 | %.o:%.cp 208 | $(COMPILE.cxx) $< -o $@ 209 | 210 | %.o:%.cxx 211 | $(COMPILE.cxx) $< -o $@ 212 | 213 | # Rules for generating the tags. 214 | #------------------------------------- 215 | tags: $(HEADERS) $(SOURCES) 216 | $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES) 217 | 218 | ctags: $(HEADERS) $(SOURCES) 219 | $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES) 220 | 221 | # Rules for generating the executable. 222 | #------------------------------------- 223 | $(PROGRAM):$(OBJS) 224 | ifeq ($(SRC_CXX),) # C program 225 | $(LINK.c) $(OBJS) $(MY_LIBS) -o $@ 226 | @echo Type ./$@ to execute the program. 227 | else # C++ program 228 | $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@ 229 | @echo Type ./$@ to execute the program. 230 | endif 231 | 232 | ifndef NODEP 233 | ifneq ($(DEPS),) 234 | sinclude $(DEPS) 235 | endif 236 | endif 237 | 238 | clean: 239 | $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe 240 | 241 | distclean: clean 242 | $(RM) $(DEPS) TAGS 243 | 244 | # Show help. 245 | help: 246 | @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' 247 | @echo 'Copyright (C) 2007, 2008 whyglinux ' 248 | @echo 249 | @echo 'Usage: make [TARGET]' 250 | @echo 'TARGETS:' 251 | @echo ' all (=make) compile and link.' 252 | @echo ' NODEP=yes make without generating dependencies.' 253 | @echo ' objs compile only (no linking).' 254 | @echo ' tags create tags for Emacs editor.' 255 | @echo ' ctags create ctags for VI editor.' 256 | @echo ' clean clean objects and the executable file.' 257 | @echo ' distclean clean objects, the executable and dependencies.' 258 | @echo ' show show variables (for debug use only).' 259 | @echo ' help print this message.' 260 | @echo 261 | @echo 'Report bugs to .' 262 | 263 | # Show variables (for debug use only.) 264 | show: 265 | @echo 'PROGRAM :' $(PROGRAM) 266 | @echo 'SRCDIRS :' $(SRCDIRS) 267 | @echo 'HEADERS :' $(HEADERS) 268 | @echo 'SOURCES :' $(SOURCES) 269 | @echo 'SRC_CXX :' $(SRC_CXX) 270 | @echo 'OBJS :' $(OBJS) 271 | @echo 'DEPS :' $(DEPS) 272 | @echo 'DEPEND :' $(DEPEND) 273 | @echo 'COMPILE.c :' $(COMPILE.c) 274 | @echo 'COMPILE.cxx :' $(COMPILE.cxx) 275 | @echo 'link.c :' $(LINK.c) 276 | @echo 'link.cxx :' $(LINK.cxx) 277 | 278 | ## End of the Makefile ## Suggestions are welcome ## All rights reserved ## 279 | ############################################################################# 280 | -------------------------------------------------------------------------------- /CircularBuffer/README.md: -------------------------------------------------------------------------------- 1 |

Circular Buffer

2 |
3 | 4 | A fixed data structure written in c with generic items to hold. The structure 5 | is usefull in cases when structures are rather big and/or need to ensure 6 | they don't get too big. -------------------------------------------------------------------------------- /CircularBuffer/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/6/13 4 | * 5 | * A LIFO (Last In First Out) 6 | * data-structure of generic 7 | * items. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "CircularBuffer.h" 14 | 15 | void destroy_function(void * data){ 16 | data = 0; 17 | } 18 | 19 | int main(int argc, char ** arcv){ 20 | CircularBuffer * cb = circularbuffer_initialize(10, (void *)'0'); 21 | int i; 22 | 23 | // Load buffer, plus one extra 24 | for(i=0; i<20; i++){ 25 | circularbuffer_add( cb, (void *)('A' + i) ); 26 | } 27 | 28 | // Read the buffer 29 | for(i=0; i<10; i++){ 30 | printf( "%d: %c\n", i, circularbuffer_read(cb) ); 31 | } 32 | 33 | // Destroy buffer 34 | circularbuffer_destroy(cb, destroy_function); 35 | 36 | // Destroy local handle 37 | free(cb); 38 | 39 | return(0); 40 | } 41 | -------------------------------------------------------------------------------- /HashTable/HashTable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/2/13 4 | * 5 | * Implementation file for HashTable. 6 | * 7 | * After ten collisions (ie. ten items in 8 | * a particular hash items list) the hash 9 | * table will expand to the maxCollision 10 | * plus the growthFactor. 11 | */ 12 | 13 | #include 14 | 15 | #include "HashTable.h" 16 | 17 | HashTable * hashtable_initialize(size_t size, size_t mc, size_t gf, hash_function fn, compare_equal efn){ 18 | size_t i; 19 | HashTable * ht = (HashTable *) malloc( sizeof(HashTable) ); 20 | 21 | if (ht == NULL) { 22 | printf("\nERROR: Cannot create hash table. Terminating..."); 23 | exit(EXIT_FAILURE); // well... any other implementation could be added, instead of this. 24 | } 25 | 26 | ht->hf = fn; 27 | ht->eq = efn; 28 | ht->size = size; 29 | ht->maxCollisions = mc; 30 | ht->growthFactor = gf; 31 | 32 | ht->table = (Item **) malloc(size * sizeof( Item * )); 33 | 34 | if (ht->table == NULL) { 35 | printf("\nERROR: Cannot create hash table. Terminating..."); 36 | exit(EXIT_FAILURE); // well... any other implementation could be added, instead of this. 37 | } 38 | 39 | for(i=0; itable[i] = 0; 41 | } 42 | 43 | return(ht); 44 | } 45 | 46 | void * hashtable_get(HashTable * ht, void * key){ 47 | size_t hash = ht->hf(key); 48 | Item * next = ht->table[ hash % ht->size ]; 49 | 50 | while(next){ 51 | if(ht->eq( next->key, key )){ 52 | return( next->value ); 53 | }else{ 54 | next = next->next; 55 | } 56 | } 57 | 58 | return( (void *)0 ); 59 | } 60 | 61 | int hashtable_destroy(HashTable * ht){ 62 | 63 | // Avoiding runtime errors. Return a successful destroy when the 64 | // hashtable has not been initialized using the 'hashtable_initialize' 65 | // function. 66 | 67 | if (ht == NULL) 68 | return 1; 69 | 70 | // From here we know the hashtable has been properly initialized so, 71 | // we continue computations. 72 | 73 | size_t i; 74 | 75 | for(i=0; isize; i++){ 76 | free(ht->table[i]); 77 | } 78 | 79 | free(ht->table); 80 | free(ht); 81 | 82 | return(1); 83 | } 84 | 85 | int hashtable_resize(HashTable * ht, size_t size){ 86 | HashTable * newht = hashtable_initialize(size, ht->maxCollisions, ht->growthFactor, ht->hf, ht->eq); 87 | int i; 88 | Item * next; 89 | 90 | // Re-enter all the items again into the new hashtable 91 | // with the new size. 92 | for(i=0; isize; i++){ 93 | if(ht->table[i]){ 94 | for(next=ht->table[i]; next; next=next->next){ 95 | hashtable_add(newht, next->key, next->value); 96 | } 97 | } 98 | 99 | hashtable_remove(ht, ht->table[i]->key); 100 | } 101 | 102 | free(ht->table); 103 | newht->size = ht->size; 104 | newht->table = ht->table; 105 | 106 | return(1); 107 | } 108 | 109 | int hashtable_add(HashTable * ht, void * key, void * value){ 110 | size_t hash = ht->hf(key); 111 | Item * next = ht->table[ hash % ht->size ]; 112 | size_t i = 0; 113 | 114 | while(next){ 115 | // Replace data if key is same 116 | if(ht->eq( next->key, key )){ 117 | next->value = value; 118 | return(1); 119 | } 120 | 121 | next = next->next; 122 | i++; 123 | } 124 | 125 | next = (Item *)malloc( sizeof(Item) ); 126 | 127 | // Making sure that memory was properly allocated for 'next'. 128 | if (next == NULL) { 129 | printf("\nERROR: Insufficient memory. Terminating...."); 130 | exit(EXIT_FAILURE); // some other implementation could be used here. 131 | } 132 | 133 | next->key = key; 134 | next->value = value; 135 | next->next = ht->table[ hash % ht->size ]; 136 | ht->table[ hash % ht->size ] = next; 137 | 138 | if(i >= ht->maxCollisions){ 139 | hashtable_resize(ht, ht->size + ht->growthFactor); 140 | } 141 | 142 | return(1); 143 | } 144 | 145 | int hashtable_remove(HashTable * ht, void * key){ 146 | size_t hash = ht->hf(key); 147 | Item * next = ht->table[ hash % ht->size ]; 148 | Item * prev = 0; 149 | 150 | while(next){ 151 | if(ht->eq( next->key, key )){ 152 | if(prev){ 153 | prev->next = next->next; 154 | }else{ 155 | ht->table[ hash % ht->size ] = next->next; 156 | } 157 | 158 | free(next); 159 | 160 | return(1); 161 | } 162 | 163 | prev = next; 164 | next = next->next; 165 | } 166 | 167 | return(0); 168 | } 169 | -------------------------------------------------------------------------------- /HashTable/HashTable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/2/13 4 | * 5 | * Implementation file for HashTable. 6 | * 7 | * After ten collisions (ie. ten items in 8 | * a particular hash items list) the hash 9 | * table will expand to the maxCollision 10 | * plus the growthFactor. 11 | */ 12 | 13 | #ifndef __HASHTABLE_H__ 14 | #define __HASHTABLE_H__ 15 | 16 | typedef size_t (* hash_function)(void *); 17 | typedef size_t (* compare_equal)(void *, void *); 18 | 19 | typedef struct Item{ 20 | void * key; 21 | void * value; 22 | struct Item * next; 23 | } Item; 24 | 25 | typedef struct HashTable{ 26 | size_t size; 27 | size_t maxCollisions; 28 | size_t growthFactor; 29 | Item ** table; 30 | hash_function hf; 31 | compare_equal eq; 32 | } HashTable; 33 | 34 | /* 35 | * Creates instance of HashTable with size and 36 | * function given to create a hash of the key. 37 | * 38 | * The hash function is given so that any variable 39 | * or structure etc can be used as the key in the 40 | * key value pairing. 41 | */ 42 | HashTable * hashtable_initialize(size_t, size_t, size_t, hash_function, compare_equal); 43 | 44 | /* 45 | * Finds the value in the table in O(n) speed given 46 | * key, and returns value as void * or void * 0 on 47 | * error. 48 | */ 49 | void * hashtable_get(HashTable *, void *); 50 | 51 | /* 52 | * Free's all memory in the hash table. Returns 53 | * success status 1 true, 0 false. 54 | */ 55 | int hashtable_destroy(HashTable *); 56 | 57 | /* 58 | * Resizes the hash table to a different 59 | * size. 60 | */ 61 | int hashtable_resize(HashTable *, size_t); 62 | 63 | /* 64 | * Adds a new key value pair to the table. If 65 | * key already exists it will overwrite it. 66 | */ 67 | int hashtable_add(HashTable *, void *, void *); 68 | 69 | /* 70 | * Free's and deletes memory of a item and clears 71 | * the spot in the table. 72 | */ 73 | int hashtable_remove(HashTable *, void *); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /HashTable/README.md: -------------------------------------------------------------------------------- 1 |

HashTable

2 |
3 | 4 | 5 | A pure C way to make a hash table to hold generic data and use a generic key. 6 | 7 | 8 | The example use of the hashtable is simple but is to show the resizing capability 9 | within the hashtable. Every hashtable is O(1) on lookups, but this is with optimal 10 | hardware and minimal to no collisions. So we have a hashtable that can start at a 11 | small size and when added elements to it, it can expand to hold them with less 12 | collisions. 13 | 14 | 15 | Configural parameters in the hashtable: 16 |
    17 |
  • Starting size: Size the table will start at.
  • 18 |
  • Values to hold: Cast every value inserted into the hashtable as void * and you 19 | can use any value under the sun.
  • 20 |
  • Key to search with: Key to do hashes on and search with. Can be anything becuase 21 | the user needs to define a hash function for the hashtable returning the hash to use.
  • 22 |
  • Max collisions: Max number of collisions before table will resize to keep it 23 | at an optimal size for quickest lookups.
  • 24 |
  • Growth factor: The amount of entries to add onto the size if the max number 25 | of collisions happen. If the size of the table is large then the amount of time a 26 | resize can take can be a little while.. but worth it in most cases.
  • 27 |
28 | -------------------------------------------------------------------------------- /HashTable/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 11/2/13 4 | * 5 | * Test/example use/use case 6 | * for HashTable implementation. 7 | */ 8 | 9 | #include 10 | 11 | #include "HashTable.h" 12 | 13 | size_t hash(void * key){ 14 | size_t hash = 0; 15 | const char * k = (const char *)key; 16 | 17 | while (*k) { 18 | hash = hash*37 + *k++; 19 | } 20 | return hash; 21 | } 22 | 23 | size_t mycompare_equal(void * key1, void * key2){ 24 | if((const char *)key1 == (const char *)key2) 25 | return(1); 26 | else 27 | return(0); 28 | } 29 | 30 | int main(int argc, char ** argv){ 31 | HashTable * ht = hashtable_initialize(1, 1, 2, hash, mycompare_equal); 32 | 33 | hashtable_add(ht, (void *)"1", (void *)"ONE"); 34 | hashtable_add(ht, (void *)"2", (void *)"TWO"); 35 | hashtable_add(ht, (void *)"3", (void *)"THREE"); 36 | hashtable_add(ht, (void *)"4", (void *)"FOUR"); 37 | 38 | printf("ht[\"1\"]: %s\n", (const char *)hashtable_get(ht, (void *)"1")); 39 | printf("ht[\"2\"]: %s\n", (const char *)hashtable_get(ht, (void *)"2")); 40 | printf("ht[\"3\"]: %s\n", (const char *)hashtable_get(ht, (void *)"3")); 41 | printf("ht[\"4\"]: %s\n", (const char *)hashtable_get(ht, (void *)"4")); 42 | 43 | // Add more to inact resize 44 | 45 | hashtable_add(ht, (void *)"5", (void *)"FIVE"); 46 | hashtable_add(ht, (void *)"6", (void *)"SIX"); 47 | hashtable_add(ht, (void *)"7", (void *)"SEVEN"); 48 | hashtable_add(ht, (void *)"8", (void *)"EIGHT"); 49 | 50 | printf("ht[\"5\"]: %s\n", (const char *)hashtable_get(ht, (void *)"5")); 51 | printf("ht[\"6\"]: %s\n", (const char *)hashtable_get(ht, (void *)"6")); 52 | printf("ht[\"7\"]: %s\n", (const char *)hashtable_get(ht, (void *)"7")); 53 | printf("ht[\"8\"]: %s\n", (const char *)hashtable_get(ht, (void *)"8")); 54 | 55 | hashtable_destroy(ht); 56 | 57 | return(0); 58 | } 59 | -------------------------------------------------------------------------------- /HashTable/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # 3 | # Generic Makefile for C/C++ Program 4 | # 5 | # License: GPL (General Public License) 6 | # Author: whyglinux 7 | # Date: 2006/03/04 (version 0.1) 8 | # 2007/03/24 (version 0.2) 9 | # 2007/04/09 (version 0.3) 10 | # 2007/06/26 (version 0.4) 11 | # 2008/04/05 (version 0.5) 12 | # 13 | # Description: 14 | # ------------ 15 | # This is an easily customizable makefile template. The purpose is to 16 | # provide an instant building environment for C/C++ programs. 17 | # 18 | # It searches all the C/C++ source files in the specified directories, 19 | # makes dependencies, compiles and links to form an executable. 20 | # 21 | # Besides its default ability to build C/C++ programs which use only 22 | # standard C/C++ libraries, you can customize the Makefile to build 23 | # those using other libraries. Once done, without any changes you can 24 | # then build programs using the same or less libraries, even if source 25 | # files are renamed, added or removed. Therefore, it is particularly 26 | # convenient to use it to build codes for experimental or study use. 27 | # 28 | # GNU make is expected to use the Makefile. Other versions of makes 29 | # may or may not work. 30 | # 31 | # Usage: 32 | # ------ 33 | # 1. Copy the Makefile to your program directory. 34 | # 2. Customize in the "Customizable Section" only if necessary: 35 | # * to use non-standard C/C++ libraries, set pre-processor or compiler 36 | # options to and linker ones to 37 | # (See Makefile.gtk+-2.0 for an example) 38 | # * to search sources in more directories, set to 39 | # * to specify your favorite program name, set to 40 | # 3. Type make to start building your program. 41 | # 42 | # Make Target: 43 | # ------------ 44 | # The Makefile provides the following targets to make: 45 | # $ make compile and link 46 | # $ make NODEP=yes compile and link without generating dependencies 47 | # $ make objs compile only (no linking) 48 | # $ make tags create tags for Emacs editor 49 | # $ make ctags create ctags for VI editor 50 | # $ make clean clean objects and the executable file 51 | # $ make distclean clean objects, the executable and dependencies 52 | # $ make help get the usage of the makefile 53 | # 54 | #=========================================================================== 55 | 56 | ## Customizable Section: adapt those variables to suit your program. 57 | ##========================================================================== 58 | 59 | # The pre-processor and compiler options. 60 | MY_CFLAGS = 61 | 62 | # The linker options. 63 | MY_LIBS = 64 | 65 | # The pre-processor options used by the cpp (man cpp for more). 66 | CPPFLAGS = -Wall 67 | 68 | # The options used in linking as well as in any direct use of ld. 69 | LDFLAGS = 70 | 71 | # The directories in which source files reside. 72 | # If not specified, only the current directory will be searched. 73 | SRCDIRS = 74 | 75 | # The executable file name. 76 | # If not specified, current directory name or `a.out' will be used. 77 | PROGRAM = main 78 | 79 | ## Implicit Section: change the following only when necessary. 80 | ##========================================================================== 81 | 82 | # The source file types (headers excluded). 83 | # .c indicates C source files, and others C++ ones. 84 | SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp 85 | 86 | # The header file types. 87 | HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp 88 | 89 | # The pre-processor and compiler options. 90 | # Users can override those variables from the command line. 91 | CFLAGS = -g -O2 92 | CXXFLAGS= -g -O2 93 | 94 | # The C program compiler. 95 | CC = gcc 96 | 97 | # The C++ program compiler. 98 | #CXX = g++ 99 | 100 | # Un-comment the following line to compile C programs as C++ ones. 101 | #CC = $(CXX) 102 | 103 | # The command used to delete file. 104 | #RM = rm -f 105 | 106 | ETAGS = etags 107 | ETAGSFLAGS = 108 | 109 | CTAGS = ctags 110 | CTAGSFLAGS = 111 | 112 | ## Stable Section: usually no need to be changed. But you can add more. 113 | ##========================================================================== 114 | SHELL = /bin/sh 115 | EMPTY = 116 | SPACE = $(EMPTY) $(EMPTY) 117 | ifeq ($(PROGRAM),) 118 | CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))) 119 | PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES)) 120 | ifeq ($(PROGRAM),) 121 | PROGRAM = a.out 122 | endif 123 | endif 124 | ifeq ($(SRCDIRS),) 125 | SRCDIRS = . 126 | endif 127 | SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) 128 | HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS)))) 129 | SRC_CXX = $(filter-out %.c,$(SOURCES)) 130 | OBJS = $(addsuffix .o, $(basename $(SOURCES))) 131 | DEPS = $(OBJS:.o=.d) 132 | 133 | ## Define some useful variables. 134 | DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \ 135 | echo "-MM -MP"; else echo "-M"; fi ) 136 | DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) 137 | DEPEND.d = $(subst -g ,,$(DEPEND)) 138 | COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c 139 | COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c 140 | LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 141 | LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) 142 | 143 | .PHONY: all objs tags ctags clean distclean help show 144 | 145 | # Delete the default suffixes 146 | .SUFFIXES: 147 | 148 | all: $(PROGRAM) 149 | 150 | # Rules for creating dependency files (.d). 151 | #------------------------------------------ 152 | 153 | %.d:%.c 154 | @echo -n $(dir $<) > $@ 155 | @$(DEPEND.d) $< >> $@ 156 | 157 | %.d:%.C 158 | @echo -n $(dir $<) > $@ 159 | @$(DEPEND.d) $< >> $@ 160 | 161 | %.d:%.cc 162 | @echo -n $(dir $<) > $@ 163 | @$(DEPEND.d) $< >> $@ 164 | 165 | %.d:%.cpp 166 | @echo -n $(dir $<) > $@ 167 | @$(DEPEND.d) $< >> $@ 168 | 169 | %.d:%.CPP 170 | @echo -n $(dir $<) > $@ 171 | @$(DEPEND.d) $< >> $@ 172 | 173 | %.d:%.c++ 174 | @echo -n $(dir $<) > $@ 175 | @$(DEPEND.d) $< >> $@ 176 | 177 | %.d:%.cp 178 | @echo -n $(dir $<) > $@ 179 | @$(DEPEND.d) $< >> $@ 180 | 181 | %.d:%.cxx 182 | @echo -n $(dir $<) > $@ 183 | @$(DEPEND.d) $< >> $@ 184 | 185 | # Rules for generating object files (.o). 186 | #---------------------------------------- 187 | objs:$(OBJS) 188 | 189 | %.o:%.c 190 | $(COMPILE.c) $< -o $@ 191 | 192 | %.o:%.C 193 | $(COMPILE.cxx) $< -o $@ 194 | 195 | %.o:%.cc 196 | $(COMPILE.cxx) $< -o $@ 197 | 198 | %.o:%.cpp 199 | $(COMPILE.cxx) $< -o $@ 200 | 201 | %.o:%.CPP 202 | $(COMPILE.cxx) $< -o $@ 203 | 204 | %.o:%.c++ 205 | $(COMPILE.cxx) $< -o $@ 206 | 207 | %.o:%.cp 208 | $(COMPILE.cxx) $< -o $@ 209 | 210 | %.o:%.cxx 211 | $(COMPILE.cxx) $< -o $@ 212 | 213 | # Rules for generating the tags. 214 | #------------------------------------- 215 | tags: $(HEADERS) $(SOURCES) 216 | $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES) 217 | 218 | ctags: $(HEADERS) $(SOURCES) 219 | $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES) 220 | 221 | # Rules for generating the executable. 222 | #------------------------------------- 223 | $(PROGRAM):$(OBJS) 224 | ifeq ($(SRC_CXX),) # C program 225 | $(LINK.c) $(OBJS) $(MY_LIBS) -o $@ 226 | @echo Type ./$@ to execute the program. 227 | else # C++ program 228 | $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@ 229 | @echo Type ./$@ to execute the program. 230 | endif 231 | 232 | ifndef NODEP 233 | ifneq ($(DEPS),) 234 | sinclude $(DEPS) 235 | endif 236 | endif 237 | 238 | clean: 239 | $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe 240 | 241 | distclean: clean 242 | $(RM) $(DEPS) TAGS 243 | 244 | # Show help. 245 | help: 246 | @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' 247 | @echo 'Copyright (C) 2007, 2008 whyglinux ' 248 | @echo 249 | @echo 'Usage: make [TARGET]' 250 | @echo 'TARGETS:' 251 | @echo ' all (=make) compile and link.' 252 | @echo ' NODEP=yes make without generating dependencies.' 253 | @echo ' objs compile only (no linking).' 254 | @echo ' tags create tags for Emacs editor.' 255 | @echo ' ctags create ctags for VI editor.' 256 | @echo ' clean clean objects and the executable file.' 257 | @echo ' distclean clean objects, the executable and dependencies.' 258 | @echo ' show show variables (for debug use only).' 259 | @echo ' help print this message.' 260 | @echo 261 | @echo 'Report bugs to .' 262 | 263 | # Show variables (for debug use only.) 264 | show: 265 | @echo 'PROGRAM :' $(PROGRAM) 266 | @echo 'SRCDIRS :' $(SRCDIRS) 267 | @echo 'HEADERS :' $(HEADERS) 268 | @echo 'SOURCES :' $(SOURCES) 269 | @echo 'SRC_CXX :' $(SRC_CXX) 270 | @echo 'OBJS :' $(OBJS) 271 | @echo 'DEPS :' $(DEPS) 272 | @echo 'DEPEND :' $(DEPEND) 273 | @echo 'COMPILE.c :' $(COMPILE.c) 274 | @echo 'COMPILE.cxx :' $(COMPILE.cxx) 275 | @echo 'link.c :' $(LINK.c) 276 | @echo 'link.cxx :' $(LINK.cxx) 277 | 278 | ## End of the Makefile ## Suggestions are welcome ## All rights reserved ## 279 | ############################################################################# 280 | -------------------------------------------------------------------------------- /HelloWorld/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * @author jelathro 5 | * @date 2/18/13 6 | * 7 | * Print "Hello, World!" to the console 8 | */ 9 | int main(void){ 10 | printf("Hello, World!\n"); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /List/List.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/24/13 4 | * 5 | * 6 | */ 7 | 8 | #ifndef __LIST_C__ 9 | #define __LIST_C__ 10 | 11 | #include 12 | 13 | #include "List.h" 14 | 15 | /* 16 | * Given list, Creates a new empty List_t and 17 | * returns its reference. 18 | */ 19 | List_t list_initialize(){ 20 | List_t list = { NULL }; 21 | 22 | return list; 23 | } 24 | 25 | /* 26 | * Given list, Creates a new ListItem_t and adds 27 | * it to the end of the List_t. This 28 | * returns an int accordingly if 29 | * successful or not. 30 | */ 31 | int list_add_item(List_t * list, ListItem_t * li){ 32 | // Temporary "iterator" on the list 33 | ListItem_t * nextItem = list->head; 34 | 35 | // No head yet 36 | if(!list->head){ 37 | list->head = li; 38 | return(1); 39 | } 40 | 41 | // Move to the end of the list 42 | while(nextItem->next){ 43 | nextItem = nextItem->next; 44 | } 45 | 46 | // Made it to the end of the list 47 | // add the new item to the list. 48 | if(!li->next){ 49 | nextItem->next = li; 50 | }else{ 51 | return(0); 52 | } 53 | 54 | return(1); 55 | } 56 | 57 | /* 58 | * Given list, Creates a new ListItem_t and adds 59 | * it after the index given. This returns 60 | * an int accordingly if successful 61 | * or not. 62 | */ 63 | int list_add_item_after(List_t * list, int idx, ListItem_t * li){ 64 | // Temporary "iterator" on the list 65 | ListItem_t * nextItem = list->head; 66 | 67 | // Move to list index or return 1 if no such index 68 | while(idx > 0){ 69 | // Insert after last item in list 70 | if(!nextItem->next){ // Index doesn't exist 71 | return(0); 72 | }else{ 73 | nextItem = nextItem->next; 74 | idx--; 75 | } 76 | } 77 | 78 | // Add item after current "nextItem" pointed too. 79 | if(nextItem->next){ // Middle of list 80 | if(!li->next){ 81 | ListItem_t * tmpItem = list_item_initialize(); 82 | 83 | // Save next item in list 84 | tmpItem = nextItem->next; 85 | 86 | // Attach new item to current item's next pointer 87 | nextItem->next = li; 88 | 89 | // Attach "old" next item pointer 90 | li->next = tmpItem; 91 | }else{ 92 | return(0); 93 | } 94 | }else if(!nextItem->next){ // End of list 95 | if(!li->next){ 96 | nextItem->next = li; 97 | }else{ 98 | return(0); 99 | } 100 | } 101 | 102 | return(1); 103 | } 104 | 105 | /* 106 | * Given list, Creates a new ListItem_t and adds 107 | * it before the index given. This returns 108 | * an int accordingly if successful 109 | * or not. 110 | */ 111 | int list_add_item_before(List_t * list, int idx, ListItem_t * li){ 112 | // Temporary "iterator" on the list 113 | ListItem_t * nextItem = list->head; 114 | 115 | // Move to right before list index or return 1 if no such index 116 | while(idx-1 > 0){ 117 | // Insert after last item in list 118 | if(!nextItem->next){ // Index doesn't exist 119 | return(0); 120 | }else{ 121 | nextItem = nextItem->next; 122 | idx--; 123 | } 124 | } 125 | 126 | // Add item after current "nextItem" pointed too. 127 | if(nextItem->next){ // Middle of list 128 | if(!li->next){ 129 | ListItem_t * tmpItem = list_item_initialize(); 130 | 131 | // Save next item in list 132 | tmpItem = nextItem->next; 133 | 134 | // Attach new item to current item's next pointer 135 | nextItem->next = li; 136 | 137 | // Attach "old" next item pointer 138 | li->next = tmpItem; 139 | 140 | return(1); 141 | }else{ 142 | return(0); 143 | } 144 | }else if(!nextItem->next){ // End of list 145 | if(!li->next){ 146 | nextItem->next = li; 147 | return(1); 148 | }else{ 149 | return(0); 150 | } 151 | } 152 | 153 | return(0); 154 | } 155 | 156 | /* 157 | * Given list, Free's and removes head from 158 | * the List_t. 159 | */ 160 | int list_remove_item_head(List_t * list, list_item_remove_callback_func cb){ 161 | if(list->head){ 162 | // Get current head of list 163 | ListItem_t * tmp = list->head; 164 | 165 | if(list_item_remove(tmp, cb)){ 166 | // Set next item in list to be head 167 | list->head = tmp->next; 168 | 169 | // Remove old list head 170 | free(tmp); 171 | 172 | return(1); 173 | }else{ 174 | return(0); 175 | } 176 | }else{ // List is already empty 177 | return(1); 178 | } 179 | } 180 | 181 | /* 182 | * Given list, Free's and removes tail from 183 | * List_t. 184 | */ 185 | int list_remove_item_tail(List_t * list, list_item_remove_callback_func cb){ 186 | // Temporary "iterator" on the list 187 | ListItem_t * nextItem = list->head; 188 | 189 | // Move to one before end of list 190 | while(nextItem->next){ 191 | if(!nextItem->next->next){ 192 | // Remove last list item 193 | if(list_item_remove(nextItem->next, cb)){ 194 | free(nextItem->next); 195 | }else{ 196 | return(0); 197 | } 198 | 199 | nextItem->next = 0; 200 | 201 | return(1); 202 | }else{ 203 | nextItem = nextItem->next; 204 | } 205 | } 206 | 207 | return(0); 208 | } 209 | 210 | /* 211 | * Given list, Free's and removes ListItem_t 212 | * and updates list "hole". 213 | */ 214 | int list_remove_item_at(List_t * list, int idx, list_item_remove_callback_func cb){ 215 | ListItem_t * nextItem, * lastItem; 216 | 217 | if(!list->head) return(1); 218 | if(idx == 0 && !list->head->next) return list_remove_item_head(list, cb); 219 | 220 | nextItem = list->head; 221 | lastItem = NULL; 222 | 223 | // Move to index 224 | while(idx-1 > 0){ 225 | // Index does not exist 226 | if(!nextItem->next){ 227 | return(0); 228 | }else{ 229 | // Move to next Item 230 | lastItem = nextItem; 231 | nextItem = nextItem->next; 232 | } 233 | 234 | idx--; 235 | } 236 | 237 | // Last Item 238 | if(!nextItem->next){ 239 | free(nextItem); 240 | return(1); 241 | }else{ // Middle Item 242 | // Connect item before and after index 243 | lastItem->next = nextItem->next; 244 | 245 | // Free unconnected item index 246 | free(nextItem); 247 | 248 | return(1); 249 | } 250 | } 251 | 252 | /* 253 | * Given list, Free's and removes list 254 | * and returns int according to success. 255 | */ 256 | int list_remove(List_t * list, list_item_remove_callback_func cb){ 257 | // Loop through entire list removing each item 258 | while(1){ 259 | if( list_remove_item_head(list, cb) ){ 260 | if(!list->head){ 261 | break; 262 | } 263 | }else{ 264 | return(0); 265 | } 266 | } 267 | 268 | return(1); 269 | } 270 | 271 | /* 272 | * Given list and callback function, list 273 | * will loop through all LitItem_t's and 274 | * call the function for it. 275 | */ 276 | int list_for_each(List_t * list, list_item_callback_func cb){ 277 | ListItem_t * nextItem; 278 | int idx; 279 | 280 | if(!list->head) return(0); 281 | 282 | nextItem = list->head; 283 | idx = 0; 284 | 285 | while(nextItem){ 286 | cb(idx, nextItem->data); 287 | 288 | nextItem = nextItem->next; 289 | idx++; 290 | } 291 | 292 | return(1); 293 | } 294 | 295 | /* 296 | * Given list and index to find and 297 | * return ListItem_t data (void *). 298 | */ 299 | void * list_get_at(List_t * list, int idx){ 300 | ListItem_t * nextItem; 301 | 302 | if(!list->head) return( (void *)1 ); 303 | if(idx == 0) return( (void *) list->head->data ); 304 | 305 | nextItem = list->head; 306 | 307 | // Iterate to list item at index given 308 | while(idx > 0){ 309 | if(!nextItem->next){ 310 | return( (void *) -1 ); 311 | }else{ 312 | nextItem = nextItem->next; 313 | } 314 | 315 | idx--; 316 | } 317 | 318 | return( nextItem->data ); 319 | } 320 | 321 | /* 322 | * Given list and index to find and 323 | * set ListItem_t data (void *), 324 | * returns int on success accordingly. 325 | */ 326 | int list_set_at(List_t * list, void * data, int idx){ 327 | ListItem_t * nextItem; 328 | 329 | if(!list->head) return(0); 330 | if(idx == 0){ list->head->data = data; return(0); } 331 | 332 | nextItem = list->head; 333 | 334 | // Iterate to list item at index given 335 | while(idx > 0){ 336 | if(!nextItem->next){ 337 | return(0); 338 | }else{ 339 | nextItem = nextItem->next; 340 | } 341 | 342 | idx--; 343 | } 344 | 345 | // Set the item's new/updated data 346 | if(list_item_add(nextItem, data)){ 347 | return(1); 348 | } 349 | 350 | return(0); 351 | } 352 | 353 | #endif 354 | -------------------------------------------------------------------------------- /List/List.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/24/13 4 | * 5 | * Singly linked list (as compared 6 | * to a doubly linked or indexed 7 | * list) that contains generic items 8 | * called ListItem_t. 9 | */ 10 | 11 | #ifndef __LIST_H__ 12 | #define __LIST_H__ 13 | 14 | #include "ListItem.h" 15 | 16 | typedef struct List_t{ 17 | ListItem_t * head; 18 | } List_t; 19 | 20 | /* 21 | * Given list, Creates a new empty List_t and 22 | * returns its reference. 23 | */ 24 | List_t list_initialize(); 25 | 26 | /* 27 | * Given list, Creates a new ListItem_t and adds 28 | * it to the end of the List_t. This 29 | * returns an int accordingly if 30 | * successful or not. 31 | */ 32 | int list_add_item(List_t *, ListItem_t *); 33 | 34 | /* 35 | * Given list, Creates a new ListItem_t and adds 36 | * it after the index given. This returns 37 | * an int accordingly if successful 38 | * or not. 39 | */ 40 | int list_add_item_after(List_t *, int, ListItem_t *); 41 | 42 | /* 43 | * Given list, Creates a new ListItem_t and adds 44 | * it before the index given. This returns 45 | * an int accordingly if successful 46 | * or not. 47 | */ 48 | int list_add_item_before(List_t *, int, ListItem_t *); 49 | 50 | /* 51 | * Given list, Free's and removes head from 52 | * the List_t. 53 | */ 54 | int list_remove_item_head(List_t *, list_item_remove_callback_func); 55 | 56 | /* 57 | * Given list, Free's and removes tail from 58 | * List_t. 59 | */ 60 | int list_remove_item_tail(List_t *, list_item_remove_callback_func); 61 | 62 | /* 63 | * Given list, Free's and removes ListItem_t 64 | * and updates list "hole". 65 | */ 66 | int list_remove_item_at(List_t *, int, list_item_remove_callback_func); 67 | 68 | /* 69 | * Given list, Free's and removes list 70 | * and returns int according to success. 71 | */ 72 | int list_remove(List_t *, list_item_remove_callback_func); 73 | 74 | /* 75 | * Given list and callback function, list 76 | * will loop through all LitItem_t's and 77 | * call the function for it. 78 | */ 79 | int list_for_each(List_t *, list_item_callback_func); 80 | 81 | /* 82 | * Given list and index to find and 83 | * return ListItem_t data (void *). 84 | */ 85 | void * list_get_at(List_t *, int); 86 | 87 | /* 88 | * Given list and index to find and 89 | * set ListItem_t data (void *), 90 | * returns int on success accordingly. 91 | */ 92 | int list_set_at(List_t *, void *, int); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /List/ListItem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | #include 6 | 7 | #include "ListItem.h" 8 | 9 | /* 10 | * Allocates new memory for a ListItem_t 11 | * then returns a pointer to it. 12 | */ 13 | ListItem_t * list_item_initialize(){ 14 | ListItem_t * li = (ListItem_t *) malloc( sizeof(ListItem_t) ); 15 | 16 | // Making sure there was enough memory for a 'ListItem_t' type 'li'. 17 | if (li == NULL) { 18 | printf("\nERROR: Insufficient memory. Terminating..."); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | li->next = 0; 23 | 24 | return(li); 25 | } 26 | 27 | /* 28 | * Removes ListItem_t data and returns 29 | * if successful or not. 30 | */ 31 | int list_item_remove(ListItem_t * li, list_item_remove_callback_func cb){ 32 | return( cb(li->data) ); 33 | } 34 | 35 | /* 36 | * Add ListItem_t data and returns 37 | * if successful or not. 38 | */ 39 | int list_item_add(ListItem_t * li, void * data){ 40 | li->data = data; 41 | return(1); 42 | } 43 | -------------------------------------------------------------------------------- /List/ListItem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/24/13 4 | * 5 | * Generic container called ListItem_t 6 | * for template. Has a pointer to the 7 | * next item in the list and if its at 8 | * the end of the list then it will be 9 | * NULL. 10 | * 11 | * Implements only "create" and "remove" 12 | * functionality. This is because the 13 | * ListItem_t is too generic to implement 14 | * anymore, the user will need to do the 15 | * rest. 16 | */ 17 | 18 | #ifndef __LISTITEM_H__ 19 | #define __LISTITEM_H__ 20 | 21 | typedef void (* list_item_callback_func)(int, void *); 22 | typedef int (* list_item_remove_callback_func)(void *); 23 | 24 | typedef struct ListItem_t{ 25 | struct ListItem_t * next; 26 | void * data; 27 | } ListItem_t; 28 | 29 | /* 30 | * Allocates new memory for a ListItem_t 31 | * then returns a pointer to it. 32 | */ 33 | ListItem_t * list_item_initialize(); 34 | 35 | /* 36 | * Removes ListItem_t data and returns 37 | * if successful or not. 38 | */ 39 | int list_item_remove(ListItem_t *, list_item_remove_callback_func); 40 | 41 | /* 42 | * Add ListItem_t data and returns 43 | * if successful or not. 44 | */ 45 | int list_item_add(ListItem_t *, void *); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /List/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # 3 | # Generic Makefile for C/C++ Program 4 | # 5 | # License: GPL (General Public License) 6 | # Author: whyglinux 7 | # Date: 2006/03/04 (version 0.1) 8 | # 2007/03/24 (version 0.2) 9 | # 2007/04/09 (version 0.3) 10 | # 2007/06/26 (version 0.4) 11 | # 2008/04/05 (version 0.5) 12 | # 13 | # Description: 14 | # ------------ 15 | # This is an easily customizable makefile template. The purpose is to 16 | # provide an instant building environment for C/C++ programs. 17 | # 18 | # It searches all the C/C++ source files in the specified directories, 19 | # makes dependencies, compiles and links to form an executable. 20 | # 21 | # Besides its default ability to build C/C++ programs which use only 22 | # standard C/C++ libraries, you can customize the Makefile to build 23 | # those using other libraries. Once done, without any changes you can 24 | # then build programs using the same or less libraries, even if source 25 | # files are renamed, added or removed. Therefore, it is particularly 26 | # convenient to use it to build codes for experimental or study use. 27 | # 28 | # GNU make is expected to use the Makefile. Other versions of makes 29 | # may or may not work. 30 | # 31 | # Usage: 32 | # ------ 33 | # 1. Copy the Makefile to your program directory. 34 | # 2. Customize in the "Customizable Section" only if necessary: 35 | # * to use non-standard C/C++ libraries, set pre-processor or compiler 36 | # options to and linker ones to 37 | # (See Makefile.gtk+-2.0 for an example) 38 | # * to search sources in more directories, set to 39 | # * to specify your favorite program name, set to 40 | # 3. Type make to start building your program. 41 | # 42 | # Make Target: 43 | # ------------ 44 | # The Makefile provides the following targets to make: 45 | # $ make compile and link 46 | # $ make NODEP=yes compile and link without generating dependencies 47 | # $ make objs compile only (no linking) 48 | # $ make tags create tags for Emacs editor 49 | # $ make ctags create ctags for VI editor 50 | # $ make clean clean objects and the executable file 51 | # $ make distclean clean objects, the executable and dependencies 52 | # $ make help get the usage of the makefile 53 | # 54 | #=========================================================================== 55 | 56 | ## Customizable Section: adapt those variables to suit your program. 57 | ##========================================================================== 58 | 59 | # The pre-processor and compiler options. 60 | MY_CFLAGS = 61 | 62 | # The linker options. 63 | MY_LIBS = 64 | 65 | # The pre-processor options used by the cpp (man cpp for more). 66 | CPPFLAGS = -Wall 67 | 68 | # The options used in linking as well as in any direct use of ld. 69 | LDFLAGS = 70 | 71 | # The directories in which source files reside. 72 | # If not specified, only the current directory will be searched. 73 | SRCDIRS = 74 | 75 | # The executable file name. 76 | # If not specified, current directory name or `a.out' will be used. 77 | PROGRAM = main 78 | 79 | ## Implicit Section: change the following only when necessary. 80 | ##========================================================================== 81 | 82 | # The source file types (headers excluded). 83 | # .c indicates C source files, and others C++ ones. 84 | SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp 85 | 86 | # The header file types. 87 | HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp 88 | 89 | # The pre-processor and compiler options. 90 | # Users can override those variables from the command line. 91 | CFLAGS = -g -O2 92 | CXXFLAGS= -g -O2 93 | 94 | # The C program compiler. 95 | CC = gcc 96 | 97 | # The C++ program compiler. 98 | #CXX = g++ 99 | 100 | # Un-comment the following line to compile C programs as C++ ones. 101 | #CC = $(CXX) 102 | 103 | # The command used to delete file. 104 | #RM = rm -f 105 | 106 | ETAGS = etags 107 | ETAGSFLAGS = 108 | 109 | CTAGS = ctags 110 | CTAGSFLAGS = 111 | 112 | ## Stable Section: usually no need to be changed. But you can add more. 113 | ##========================================================================== 114 | SHELL = /bin/sh 115 | EMPTY = 116 | SPACE = $(EMPTY) $(EMPTY) 117 | ifeq ($(PROGRAM),) 118 | CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))) 119 | PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES)) 120 | ifeq ($(PROGRAM),) 121 | PROGRAM = a.out 122 | endif 123 | endif 124 | ifeq ($(SRCDIRS),) 125 | SRCDIRS = . 126 | endif 127 | SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) 128 | HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS)))) 129 | SRC_CXX = $(filter-out %.c,$(SOURCES)) 130 | OBJS = $(addsuffix .o, $(basename $(SOURCES))) 131 | DEPS = $(OBJS:.o=.d) 132 | 133 | ## Define some useful variables. 134 | DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \ 135 | echo "-MM -MP"; else echo "-M"; fi ) 136 | DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) 137 | DEPEND.d = $(subst -g ,,$(DEPEND)) 138 | COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c 139 | COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c 140 | LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 141 | LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) 142 | 143 | .PHONY: all objs tags ctags clean distclean help show 144 | 145 | # Delete the default suffixes 146 | .SUFFIXES: 147 | 148 | all: $(PROGRAM) 149 | 150 | # Rules for creating dependency files (.d). 151 | #------------------------------------------ 152 | 153 | %.d:%.c 154 | @echo -n $(dir $<) > $@ 155 | @$(DEPEND.d) $< >> $@ 156 | 157 | %.d:%.C 158 | @echo -n $(dir $<) > $@ 159 | @$(DEPEND.d) $< >> $@ 160 | 161 | %.d:%.cc 162 | @echo -n $(dir $<) > $@ 163 | @$(DEPEND.d) $< >> $@ 164 | 165 | %.d:%.cpp 166 | @echo -n $(dir $<) > $@ 167 | @$(DEPEND.d) $< >> $@ 168 | 169 | %.d:%.CPP 170 | @echo -n $(dir $<) > $@ 171 | @$(DEPEND.d) $< >> $@ 172 | 173 | %.d:%.c++ 174 | @echo -n $(dir $<) > $@ 175 | @$(DEPEND.d) $< >> $@ 176 | 177 | %.d:%.cp 178 | @echo -n $(dir $<) > $@ 179 | @$(DEPEND.d) $< >> $@ 180 | 181 | %.d:%.cxx 182 | @echo -n $(dir $<) > $@ 183 | @$(DEPEND.d) $< >> $@ 184 | 185 | # Rules for generating object files (.o). 186 | #---------------------------------------- 187 | objs:$(OBJS) 188 | 189 | %.o:%.c 190 | $(COMPILE.c) $< -o $@ 191 | 192 | %.o:%.C 193 | $(COMPILE.cxx) $< -o $@ 194 | 195 | %.o:%.cc 196 | $(COMPILE.cxx) $< -o $@ 197 | 198 | %.o:%.cpp 199 | $(COMPILE.cxx) $< -o $@ 200 | 201 | %.o:%.CPP 202 | $(COMPILE.cxx) $< -o $@ 203 | 204 | %.o:%.c++ 205 | $(COMPILE.cxx) $< -o $@ 206 | 207 | %.o:%.cp 208 | $(COMPILE.cxx) $< -o $@ 209 | 210 | %.o:%.cxx 211 | $(COMPILE.cxx) $< -o $@ 212 | 213 | # Rules for generating the tags. 214 | #------------------------------------- 215 | tags: $(HEADERS) $(SOURCES) 216 | $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES) 217 | 218 | ctags: $(HEADERS) $(SOURCES) 219 | $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES) 220 | 221 | # Rules for generating the executable. 222 | #------------------------------------- 223 | $(PROGRAM):$(OBJS) 224 | ifeq ($(SRC_CXX),) # C program 225 | $(LINK.c) $(OBJS) $(MY_LIBS) -o $@ 226 | @echo Type ./$@ to execute the program. 227 | else # C++ program 228 | $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@ 229 | @echo Type ./$@ to execute the program. 230 | endif 231 | 232 | ifndef NODEP 233 | ifneq ($(DEPS),) 234 | sinclude $(DEPS) 235 | endif 236 | endif 237 | 238 | clean: 239 | $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe 240 | 241 | distclean: clean 242 | $(RM) $(DEPS) TAGS 243 | 244 | # Show help. 245 | help: 246 | @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' 247 | @echo 'Copyright (C) 2007, 2008 whyglinux ' 248 | @echo 249 | @echo 'Usage: make [TARGET]' 250 | @echo 'TARGETS:' 251 | @echo ' all (=make) compile and link.' 252 | @echo ' NODEP=yes make without generating dependencies.' 253 | @echo ' objs compile only (no linking).' 254 | @echo ' tags create tags for Emacs editor.' 255 | @echo ' ctags create ctags for VI editor.' 256 | @echo ' clean clean objects and the executable file.' 257 | @echo ' distclean clean objects, the executable and dependencies.' 258 | @echo ' show show variables (for debug use only).' 259 | @echo ' help print this message.' 260 | @echo 261 | @echo 'Report bugs to .' 262 | 263 | # Show variables (for debug use only.) 264 | show: 265 | @echo 'PROGRAM :' $(PROGRAM) 266 | @echo 'SRCDIRS :' $(SRCDIRS) 267 | @echo 'HEADERS :' $(HEADERS) 268 | @echo 'SOURCES :' $(SOURCES) 269 | @echo 'SRC_CXX :' $(SRC_CXX) 270 | @echo 'OBJS :' $(OBJS) 271 | @echo 'DEPS :' $(DEPS) 272 | @echo 'DEPEND :' $(DEPEND) 273 | @echo 'COMPILE.c :' $(COMPILE.c) 274 | @echo 'COMPILE.cxx :' $(COMPILE.cxx) 275 | @echo 'link.c :' $(LINK.c) 276 | @echo 'link.cxx :' $(LINK.cxx) 277 | 278 | ## End of the Makefile ## Suggestions are welcome ## All rights reserved ## 279 | ############################################################################# 280 | -------------------------------------------------------------------------------- /List/README.md: -------------------------------------------------------------------------------- 1 | List 2 | ==== 3 | -------------------------------------------------------------------------------- /List/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/24/13 4 | * 5 | * Example program using the 6 | * generic list data structure 7 | * implemented in List.h. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "List.h" 14 | 15 | void print_list_item(int idx, void * data){ 16 | printf("%d: %d, ", idx, (int) data); 17 | } 18 | 19 | int delete_list_item(void * data){ 20 | return(1); 21 | } 22 | 23 | int main(int argc, char ** argv){ 24 | int data = 0; 25 | List_t list_int; 26 | ListItem_t * li; 27 | 28 | // Create an empty list 29 | list_int = list_initialize(); 30 | 31 | // Add items to list of type int casted 32 | // to void * for the list to operate with it. 33 | for(data=0; data < 10; data++){ 34 | // Add item to list ( adds to the end ) 35 | li = list_item_initialize(); 36 | list_item_add( li, (void *) data ); 37 | list_add_item(& list_int, li); 38 | } 39 | 40 | // Print contents of the list 41 | list_for_each(& list_int, print_list_item); 42 | printf("\n=============================\n"); 43 | 44 | // Add item after first one 45 | li = list_item_initialize(); 46 | list_item_add(li, (void *) -1 ); 47 | list_add_item_after(& list_int, 0, li); 48 | 49 | // Add item before second one 50 | li = list_item_initialize(); 51 | list_item_add(li, (void *) -2 ); 52 | list_add_item_before(& list_int, 2, li); 53 | 54 | // Print contents of the list 55 | list_for_each(& list_int, print_list_item); 56 | printf("\n=============================\n"); 57 | 58 | list_remove_item_head(& list_int, delete_list_item); 59 | list_remove_item_tail(& list_int, delete_list_item); 60 | list_remove_item_at(& list_int, 5, delete_list_item); 61 | 62 | list_set_at(& list_int, (void *) 100, 7); 63 | 64 | // Print contents of the list 65 | list_for_each(& list_int, print_list_item); 66 | printf("\n=============================\n"); 67 | 68 | // Remove the list 69 | list_remove(& list_int, delete_list_item); 70 | 71 | return(0); 72 | } 73 | -------------------------------------------------------------------------------- /Queue/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # 3 | # Generic Makefile for C/C++ Program 4 | # 5 | # License: GPL (General Public License) 6 | # Author: whyglinux 7 | # Date: 2006/03/04 (version 0.1) 8 | # 2007/03/24 (version 0.2) 9 | # 2007/04/09 (version 0.3) 10 | # 2007/06/26 (version 0.4) 11 | # 2008/04/05 (version 0.5) 12 | # 13 | # Description: 14 | # ------------ 15 | # This is an easily customizable makefile template. The purpose is to 16 | # provide an instant building environment for C/C++ programs. 17 | # 18 | # It searches all the C/C++ source files in the specified directories, 19 | # makes dependencies, compiles and links to form an executable. 20 | # 21 | # Besides its default ability to build C/C++ programs which use only 22 | # standard C/C++ libraries, you can customize the Makefile to build 23 | # those using other libraries. Once done, without any changes you can 24 | # then build programs using the same or less libraries, even if source 25 | # files are renamed, added or removed. Therefore, it is particularly 26 | # convenient to use it to build codes for experimental or study use. 27 | # 28 | # GNU make is expected to use the Makefile. Other versions of makes 29 | # may or may not work. 30 | # 31 | # Usage: 32 | # ------ 33 | # 1. Copy the Makefile to your program directory. 34 | # 2. Customize in the "Customizable Section" only if necessary: 35 | # * to use non-standard C/C++ libraries, set pre-processor or compiler 36 | # options to and linker ones to 37 | # (See Makefile.gtk+-2.0 for an example) 38 | # * to search sources in more directories, set to 39 | # * to specify your favorite program name, set to 40 | # 3. Type make to start building your program. 41 | # 42 | # Make Target: 43 | # ------------ 44 | # The Makefile provides the following targets to make: 45 | # $ make compile and link 46 | # $ make NODEP=yes compile and link without generating dependencies 47 | # $ make objs compile only (no linking) 48 | # $ make tags create tags for Emacs editor 49 | # $ make ctags create ctags for VI editor 50 | # $ make clean clean objects and the executable file 51 | # $ make distclean clean objects, the executable and dependencies 52 | # $ make help get the usage of the makefile 53 | # 54 | #=========================================================================== 55 | 56 | ## Customizable Section: adapt those variables to suit your program. 57 | ##========================================================================== 58 | 59 | # The pre-processor and compiler options. 60 | MY_CFLAGS = 61 | 62 | # The linker options. 63 | MY_LIBS = 64 | 65 | # The pre-processor options used by the cpp (man cpp for more). 66 | CPPFLAGS = -Wall 67 | 68 | # The options used in linking as well as in any direct use of ld. 69 | LDFLAGS = 70 | 71 | # The directories in which source files reside. 72 | # If not specified, only the current directory will be searched. 73 | SRCDIRS = 74 | 75 | # The executable file name. 76 | # If not specified, current directory name or `a.out' will be used. 77 | PROGRAM = main 78 | 79 | ## Implicit Section: change the following only when necessary. 80 | ##========================================================================== 81 | 82 | # The source file types (headers excluded). 83 | # .c indicates C source files, and others C++ ones. 84 | SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp 85 | 86 | # The header file types. 87 | HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp 88 | 89 | # The pre-processor and compiler options. 90 | # Users can override those variables from the command line. 91 | CFLAGS = -g -O2 92 | CXXFLAGS= -g -O2 93 | 94 | # The C program compiler. 95 | CC = gcc 96 | 97 | # The C++ program compiler. 98 | #CXX = g++ 99 | 100 | # Un-comment the following line to compile C programs as C++ ones. 101 | #CC = $(CXX) 102 | 103 | # The command used to delete file. 104 | #RM = rm -f 105 | 106 | ETAGS = etags 107 | ETAGSFLAGS = 108 | 109 | CTAGS = ctags 110 | CTAGSFLAGS = 111 | 112 | ## Stable Section: usually no need to be changed. But you can add more. 113 | ##========================================================================== 114 | SHELL = /bin/sh 115 | EMPTY = 116 | SPACE = $(EMPTY) $(EMPTY) 117 | ifeq ($(PROGRAM),) 118 | CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))) 119 | PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES)) 120 | ifeq ($(PROGRAM),) 121 | PROGRAM = a.out 122 | endif 123 | endif 124 | ifeq ($(SRCDIRS),) 125 | SRCDIRS = . 126 | endif 127 | SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) 128 | HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS)))) 129 | SRC_CXX = $(filter-out %.c,$(SOURCES)) 130 | OBJS = $(addsuffix .o, $(basename $(SOURCES))) 131 | DEPS = $(OBJS:.o=.d) 132 | 133 | ## Define some useful variables. 134 | DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \ 135 | echo "-MM -MP"; else echo "-M"; fi ) 136 | DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) 137 | DEPEND.d = $(subst -g ,,$(DEPEND)) 138 | COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c 139 | COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c 140 | LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) 141 | LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) 142 | 143 | .PHONY: all objs tags ctags clean distclean help show 144 | 145 | # Delete the default suffixes 146 | .SUFFIXES: 147 | 148 | all: $(PROGRAM) 149 | 150 | # Rules for creating dependency files (.d). 151 | #------------------------------------------ 152 | 153 | %.d:%.c 154 | @echo -n $(dir $<) > $@ 155 | @$(DEPEND.d) $< >> $@ 156 | 157 | %.d:%.C 158 | @echo -n $(dir $<) > $@ 159 | @$(DEPEND.d) $< >> $@ 160 | 161 | %.d:%.cc 162 | @echo -n $(dir $<) > $@ 163 | @$(DEPEND.d) $< >> $@ 164 | 165 | %.d:%.cpp 166 | @echo -n $(dir $<) > $@ 167 | @$(DEPEND.d) $< >> $@ 168 | 169 | %.d:%.CPP 170 | @echo -n $(dir $<) > $@ 171 | @$(DEPEND.d) $< >> $@ 172 | 173 | %.d:%.c++ 174 | @echo -n $(dir $<) > $@ 175 | @$(DEPEND.d) $< >> $@ 176 | 177 | %.d:%.cp 178 | @echo -n $(dir $<) > $@ 179 | @$(DEPEND.d) $< >> $@ 180 | 181 | %.d:%.cxx 182 | @echo -n $(dir $<) > $@ 183 | @$(DEPEND.d) $< >> $@ 184 | 185 | # Rules for generating object files (.o). 186 | #---------------------------------------- 187 | objs:$(OBJS) 188 | 189 | %.o:%.c 190 | $(COMPILE.c) $< -o $@ 191 | 192 | %.o:%.C 193 | $(COMPILE.cxx) $< -o $@ 194 | 195 | %.o:%.cc 196 | $(COMPILE.cxx) $< -o $@ 197 | 198 | %.o:%.cpp 199 | $(COMPILE.cxx) $< -o $@ 200 | 201 | %.o:%.CPP 202 | $(COMPILE.cxx) $< -o $@ 203 | 204 | %.o:%.c++ 205 | $(COMPILE.cxx) $< -o $@ 206 | 207 | %.o:%.cp 208 | $(COMPILE.cxx) $< -o $@ 209 | 210 | %.o:%.cxx 211 | $(COMPILE.cxx) $< -o $@ 212 | 213 | # Rules for generating the tags. 214 | #------------------------------------- 215 | tags: $(HEADERS) $(SOURCES) 216 | $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES) 217 | 218 | ctags: $(HEADERS) $(SOURCES) 219 | $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES) 220 | 221 | # Rules for generating the executable. 222 | #------------------------------------- 223 | $(PROGRAM):$(OBJS) 224 | ifeq ($(SRC_CXX),) # C program 225 | $(LINK.c) $(OBJS) $(MY_LIBS) -o $@ 226 | @echo Type ./$@ to execute the program. 227 | else # C++ program 228 | $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@ 229 | @echo Type ./$@ to execute the program. 230 | endif 231 | 232 | ifndef NODEP 233 | ifneq ($(DEPS),) 234 | sinclude $(DEPS) 235 | endif 236 | endif 237 | 238 | clean: 239 | $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe 240 | 241 | distclean: clean 242 | $(RM) $(DEPS) TAGS 243 | 244 | # Show help. 245 | help: 246 | @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' 247 | @echo 'Copyright (C) 2007, 2008 whyglinux ' 248 | @echo 249 | @echo 'Usage: make [TARGET]' 250 | @echo 'TARGETS:' 251 | @echo ' all (=make) compile and link.' 252 | @echo ' NODEP=yes make without generating dependencies.' 253 | @echo ' objs compile only (no linking).' 254 | @echo ' tags create tags for Emacs editor.' 255 | @echo ' ctags create ctags for VI editor.' 256 | @echo ' clean clean objects and the executable file.' 257 | @echo ' distclean clean objects, the executable and dependencies.' 258 | @echo ' show show variables (for debug use only).' 259 | @echo ' help print this message.' 260 | @echo 261 | @echo 'Report bugs to .' 262 | 263 | # Show variables (for debug use only.) 264 | show: 265 | @echo 'PROGRAM :' $(PROGRAM) 266 | @echo 'SRCDIRS :' $(SRCDIRS) 267 | @echo 'HEADERS :' $(HEADERS) 268 | @echo 'SOURCES :' $(SOURCES) 269 | @echo 'SRC_CXX :' $(SRC_CXX) 270 | @echo 'OBJS :' $(OBJS) 271 | @echo 'DEPS :' $(DEPS) 272 | @echo 'DEPEND :' $(DEPEND) 273 | @echo 'COMPILE.c :' $(COMPILE.c) 274 | @echo 'COMPILE.cxx :' $(COMPILE.cxx) 275 | @echo 'link.c :' $(LINK.c) 276 | @echo 'link.cxx :' $(LINK.cxx) 277 | 278 | ## End of the Makefile ## Suggestions are welcome ## All rights reserved ## 279 | ############################################################################# 280 | -------------------------------------------------------------------------------- /Queue/Queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/27/13 4 | * 5 | * Queue implementation file. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "Queue.h" 12 | 13 | Queue_t queue_initialize(){ 14 | Queue_t q = { 0, 0 }; 15 | return(q); 16 | } 17 | 18 | int queue_push(Queue_t * q, void * d){ 19 | QueueItem_t * tmp; 20 | 21 | if(q->size == 0){ 22 | q->head = (QueueItem_t *) malloc( sizeof(QueueItem_t) ); 23 | if (q->head == NULL) { 24 | printf("\nERROR: Insufficient memory. Terminating..."); 25 | exit(EXIT_FAILURE); 26 | } 27 | q->head->next = 0; 28 | q->head->data = d; 29 | }else{ 30 | tmp = q->head; 31 | q->head = (QueueItem_t *) malloc( sizeof(QueueItem_t) ); 32 | if (q->head == NULL) { 33 | printf("\nERROR: Insufficient memory. Terminating..."); 34 | exit(EXIT_FAILURE); 35 | } 36 | q->head->data = d; 37 | q->head->next = tmp; 38 | } 39 | 40 | q->size++; 41 | 42 | return(1); 43 | } 44 | 45 | int queue_pop(Queue_t * q, queue_callback_func_pop cb){ 46 | // Temporary "iterator" on the list 47 | QueueItem_t * nextItem = q->head; 48 | 49 | if(q->size == 0) return(0); 50 | 51 | if(q->size == 1){ 52 | if( cb(q->head->data) ){ 53 | free(q->head); 54 | q->size--; 55 | return(1); 56 | }else{ 57 | return(0); 58 | } 59 | } 60 | 61 | // Move to one before end of list 62 | while(nextItem->next){ 63 | if(!nextItem->next->next){ 64 | // Remove last list item 65 | if( cb(nextItem->next->data) ){ 66 | free(nextItem->next); 67 | }else{ 68 | return(0); 69 | } 70 | 71 | nextItem->next = 0; 72 | 73 | q->size--; 74 | 75 | return(1); 76 | }else{ 77 | nextItem = nextItem->next; 78 | } 79 | } 80 | 81 | return(0); 82 | } 83 | 84 | void * queue_front(Queue_t * q){ 85 | QueueItem_t * tmp = q->head; 86 | 87 | if(q->size == 0) return( (void *)0); 88 | 89 | while(tmp->next){ 90 | tmp = tmp->next; 91 | } 92 | 93 | return( tmp->data ); 94 | } 95 | 96 | void queue_for_each(Queue_t * q, queue_callback_func cb){ 97 | QueueItem_t * next = q->head; 98 | int idx = 0; 99 | 100 | if(q->size == 0) return; 101 | 102 | while(next){ 103 | cb(idx, next->data); 104 | idx++; 105 | next = next->next; 106 | } 107 | } 108 | 109 | int queue_remove(Queue_t * q, queue_callback_func_pop cb){ 110 | QueueItem_t * tmp; 111 | QueueItem_t * next = q->head; 112 | 113 | while(next){ 114 | tmp = next; 115 | next = next->next; 116 | 117 | if(cb(tmp->data)){ 118 | free(tmp); 119 | }else{ 120 | return(0); 121 | } 122 | } 123 | 124 | return(1); 125 | } 126 | -------------------------------------------------------------------------------- /Queue/Queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/27/13 4 | * 5 | * Queue implementation header 6 | * for what is available. 7 | */ 8 | 9 | #ifndef __QUEUE_H__ 10 | #define __QUEUE_H__ 11 | 12 | typedef int (* queue_callback_func)(int, void *); 13 | typedef int (* queue_callback_func_pop)(void *); 14 | 15 | typedef struct QueueItem_t{ 16 | struct QueueItem_t * next; 17 | void * data; 18 | } QueueItem_t; 19 | 20 | typedef struct Queue_t{ 21 | struct QueueItem_t * head; 22 | int size; 23 | } Queue_t; 24 | 25 | /* 26 | * Creates and returns a new 27 | * Queue_t instance. 28 | */ 29 | Queue_t queue_initialize(); 30 | 31 | /* 32 | * Adds a QueueItem_t of any value 33 | * to the back of the queue. 34 | */ 35 | int queue_push(Queue_t *, void *); 36 | 37 | /* 38 | * Removes and returns the first item added 39 | * to the queue (FIFO). 40 | */ 41 | int queue_pop(Queue_t *, queue_callback_func_pop); 42 | 43 | /* 44 | * Returns the data in the next item 45 | * in the queue. 46 | */ 47 | void * queue_front(Queue_t *); 48 | 49 | /* 50 | * Not really a queue function, nice for 51 | * debugging though. :-) 52 | */ 53 | void queue_for_each(Queue_t *, queue_callback_func); 54 | 55 | /* 56 | * Removes all data in the queue and returns 57 | * if it was successful. 58 | */ 59 | int queue_remove(Queue_t *, queue_callback_func_pop); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /Queue/README.md: -------------------------------------------------------------------------------- 1 | Queue 2 | ==== 3 | -------------------------------------------------------------------------------- /Queue/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @author: jelathro 3 | * @date: 10/27/13 4 | * 5 | * Example code use for this 6 | * pure c queue library implementation. 7 | */ 8 | 9 | #include 10 | 11 | #include "Queue.h" 12 | 13 | // Queue for each function callback 14 | int print_queue(int idx, void * data){ 15 | printf("%d: %c,", idx, (char *) data); 16 | 17 | return(1); 18 | } 19 | 20 | // Queue destroy queue item function callback 21 | int destroy_queue_item(void * data){ 22 | data = 0; 23 | 24 | return(1); 25 | } 26 | 27 | int main(int argc, char ** argv){ 28 | int i = 0; 29 | 30 | // Create Queue_t instance 31 | Queue_t queue = queue_initialize(); 32 | 33 | // Add some items in the queue 34 | for(i=0; i < 5; i++){ 35 | queue_push( & queue, (void *)('a' + i) ); 36 | } 37 | 38 | // Print out the queue (only debugging) 39 | queue_for_each(& queue, print_queue); 40 | printf("\n==============================\n"); 41 | 42 | // Start popping some items 43 | for(i=0; i < 5; i++){ 44 | queue_pop(& queue, destroy_queue_item); 45 | } 46 | 47 | // Print the queue again 48 | queue_for_each(& queue, print_queue); 49 | printf("\n==============================\n"); 50 | 51 | // Push item to empty list and view the "front" 52 | // which is the item pushed in this case. 53 | queue_push(& queue, (void *) 'z'); 54 | printf("Front: %c\n", (char *) queue_front(& queue)); 55 | 56 | // Delete queue 57 | queue_remove(& queue, destroy_queue_item); 58 | 59 | return(0); 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

C

2 |
3 | 4 | C programming libraries, tutorials, and guides. 5 | -------------------------------------------------------------------------------- /input_output/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BUF_SIZE 1024 4 | 5 | /* 6 | * @author jelathro 7 | * @data 3/19/13 8 | * 9 | * Show some of the various input output 10 | * (I/O) methods in C. 11 | */ 12 | int main(void){ 13 | // Input Output using printf 14 | // and scanf 15 | int number_entered = 0; 16 | printf("number_entered = %d\n", number_entered); 17 | scanf("%d", &number_entered); 18 | printf("number_entered = %d\n", number_entered); 19 | 20 | // Input Output using STDIN and 21 | // STDOUT 22 | char buffer[BUF_SIZE]; 23 | printf("Entering STDIN while loop\n"); 24 | while(fgets(buffer, BUF_SIZE, stdin)){ 25 | puts(buffer); 26 | } 27 | printf("You pressed control+d, so i'll leave now\n"); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /pointers/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * @author jelathro 5 | * @date 2/19/13 6 | * 7 | * Provide various examples of pointers 8 | * and how pointers work. 9 | */ 10 | int main(void){ 11 | // Basic pointers and Basic addresses 12 | int *basic_pointer; 13 | int basic_value; 14 | 15 | // Give value a literal value 16 | basic_value = 'A'; 17 | // Assign pointer to address 18 | // of literal value in value 19 | basic_pointer = &basic_value; 20 | 21 | printf("pointer is at address %p\n", &basic_pointer); 22 | printf("value at address of pointer is %c\n\n", *basic_pointer); 23 | 24 | // More advanced use of pointers 25 | // Array's are just fancy pointers 26 | char array[5] = {'a', 'A', 'b', 'z', 'M'}; 27 | char *same_array = array; 28 | char **fancy_same_array = &same_array; 29 | 30 | printf("array[3] = %c, addr = %p\n", array[3], &array[3]); 31 | printf("same_array[3] = %c, addr = %p\n", same_array[3], &same_array[3]); 32 | printf("**fancy_same_array[3] = %c, addr = %p\n", (*fancy_same_array)[3], &(*fancy_same_array)[3]); 33 | 34 | // char arrays are also just a "string" 35 | // of characters. 36 | printf("array string %s, addr = %p\n", array, &array); 37 | printf("same array string %s, addr = %p\n", same_array, &same_array); 38 | printf("fancy array string %s, addr = %p\n\n", (*fancy_same_array), &(*fancy_same_array)); 39 | 40 | // Arrays of pointers 41 | char *ptr_array[2]; 42 | char *ptr1 = NULL, *ptr2 = NULL; 43 | char char_elements[2] = {'H', 'i'}; 44 | 45 | ptr1 = &char_elements[1]; 46 | ptr2 = char_elements; 47 | 48 | ptr_array[0] = ptr2; 49 | ptr_array[1] = ptr1; 50 | 51 | printf("**ptr_array = %c\n", **ptr_array); 52 | printf("addr at **ptr_array = %p\n", &(**ptr_array)); 53 | printf("addr at **ptr_array[0] = %p\n\n", &(*ptr_array[0])); 54 | 55 | printf("*ptr_array[1] = %c\n", *ptr_array[1]); 56 | printf("addr at *ptr_array[0] = %p\n", &(**ptr_array)); 57 | printf("addr at *ptr_array[0] = %p\n", &(**ptr_array)); 58 | printf("addr at *ptr_array[1] = %p\n", &(*ptr_array[1])); 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /vpn/Makefile: -------------------------------------------------------------------------------- 1 | INC=/usr/local/ssl/include/ 2 | LIB=/usr/local/ssl/lib/ 3 | 4 | all: 5 | gcc -I$(INC) -L$(LIB) minivpn.c -o minivpn -lssl -lcrypto -ldl 6 | 7 | clean: 8 | rm -rf *~ minivpn 9 | -------------------------------------------------------------------------------- /vpn/README.md: -------------------------------------------------------------------------------- 1 |

VPN

2 |
3 | 4 | VPN written in all C using OPENSSL and TUN/TAP interface to allow a computer to computer, gateway to gateway connection. 5 | 6 | This will encrypt all connections sent out of the gateways/computers and only be able to be decrypted by the correct certificate signed by the certificate authority given. 7 | 8 | This has only been developed and tested for use on Ubuntu 12.04. OpenSSL and TUN/TAP will need to be accessable upon compilation/runtime. 9 | 10 | Will in runtime you can change your secret key (password) and refresh the connection at anytime. 11 | -------------------------------------------------------------------------------- /vpn/configure.sh: -------------------------------------------------------------------------------- 1 | cat ./configure.sh 2 | ip addr add 10.0.4.1/24 dev toto0 3 | ifconfig toto0 up 4 | route add -net 10.0.5.0 netmask 255.255.255.0 dev toto0 5 | sysctl net.ipv4.ip_forward=1 6 | route add -net 10.0.10.0 netmask 255.255.255.0 gw 10.0.20.1 7 | route add -net 10.0.10.0 netmask 255.255.255.0 dev toto0 8 | 9 | -------------------------------------------------------------------------------- /vpn/minivpn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justin-lathrop/c/45eee16020521760024a961a5893de73af0b0f3d/vpn/minivpn -------------------------------------------------------------------------------- /vpn/minivpn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tunproxy.c --- small demo program for tunneling over UDP with tun/tap 3 | * 4 | * Copyright (C) 2003 Philippe Biondi 5 | * 6 | * This program is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include /* SSLeay stuff */ 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | //#define exit(a) 49 | 50 | #define PERROR(x) do { perror(x); exit(1); } while (0) 51 | #define ERROR(x, args ...) do { fprintf(stderr,"ERROR:" x, ## args); exit(1); } while (0) 52 | #define CHK_NULL(x) if ((x)==NULL) exit (1) 53 | #define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } 54 | #define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } 55 | 56 | //#define SLEEP(a) if (DEBUG) {sleep(a);} 57 | #define SLEEP(a) {sleep(a);} 58 | 59 | #define ABORT() {killpg(getpgid(getpid()),SIGTERM);} 60 | 61 | #define CLIENT 0 62 | #define SERVER 1 63 | 64 | #define MAX_KEY_LENGTH (32) 65 | #define IV_LENGTH (16) 66 | #define BUFFER_LENGTH (4096) 67 | #define HASH_LENGTH (32) 68 | #define MAX_BLOCK_LENGTH (BUFFER_LENGTH + EVP_MAX_BLOCK_LENGTH + HASH_LENGTH) 69 | 70 | #define POKE_INTERVAL_IN_SECS 3 71 | 72 | /* from cli.cpp */ 73 | #define CCERTF "client.crt" 74 | #define CKEYF "client.key" 75 | #define CCACERT "ca.crt" 76 | 77 | /* from serv.cpp */ 78 | /* define HOME to be dir for key and cert files... */ 79 | #define HOME "./" 80 | /* Make these what you want for cert & key files */ 81 | #define SCERTF HOME "server.crt" 82 | #define SKEYF HOME "server.key" 83 | #define SCACERT HOME "ca.crt" 84 | 85 | 86 | char KEY[MAX_KEY_LENGTH+1] = "Wazaaaaaaaaaaahhhh !"; 87 | unsigned char IV[IV_LENGTH] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 88 | char pokemsg[BUFFER_LENGTH]; /* Used for client/server "poke" communication */ 89 | char msg[BUFFER_LENGTH]; /* Used for client/server SSL comm while tunnels are off and messages from parent/child */ 90 | char buf[MAX_BLOCK_LENGTH]; /* Used exclusively within child processes for tunnel/UDP transfers */ 91 | unsigned char out[MAX_BLOCK_LENGTH]; 92 | unsigned char md_value[HASH_LENGTH]; 93 | char szCommonName[512]; 94 | int md_len = 0; 95 | int DEBUG = 0; 96 | char *progname; 97 | 98 | void do_encrypt(char *in, int inl, char *out, int *outl) 99 | { 100 | EVP_CIPHER_CTX ctx; 101 | int tmpl = 0; 102 | 103 | if (DEBUG) write(1,"0", 1); 104 | EVP_CIPHER_CTX_init(&ctx); 105 | if (DEBUG) write(1,"1", 1); 106 | if(0 == EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, KEY, IV)) PERROR("EVP_EncryptInit_ex"); 107 | if (DEBUG) write(1,"2", 1); 108 | if(0 == EVP_EncryptUpdate(&ctx, out, outl, in, inl)) PERROR("EVP_EncryptUpdate"); 109 | if (DEBUG) write(1,"3", 1); 110 | if(0 == EVP_EncryptFinal_ex(&ctx, out+*outl, &tmpl)) PERROR("EVP_EncryptFinal_ex"); 111 | *outl += tmpl; 112 | if (DEBUG) write(1,"4", 1); 113 | EVP_CIPHER_CTX_cleanup(&ctx); 114 | if (DEBUG) write(1,"5", 1); 115 | } 116 | 117 | void do_decrypt(char *in, int inl, char *out, int *outl) 118 | { 119 | EVP_CIPHER_CTX ctx; 120 | int tmpl = 0; 121 | 122 | if (DEBUG) write(1,"6", 1); 123 | EVP_CIPHER_CTX_init(&ctx); 124 | if (DEBUG) write(1,"7", 1); 125 | if(0 == EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, KEY, IV)) PERROR("EVP_DecryptInit_ex"); 126 | if (DEBUG) write(1,"8", 1); 127 | if(0 == EVP_DecryptUpdate(&ctx, out, outl, in, inl)) PERROR("EVP_DecryptUpdate"); 128 | if (DEBUG) write(1,"9", 1); 129 | if(0 == EVP_DecryptFinal_ex(&ctx, out+*outl, &tmpl)) PERROR("EVP_DecryptFinal_ex"); 130 | *outl += tmpl; 131 | if (DEBUG) write(1,"a", 1); 132 | EVP_CIPHER_CTX_cleanup(&ctx); 133 | if (DEBUG) write(1,"b", 1); 134 | } 135 | 136 | int isEqual(char *h1, char *h2, int len){ 137 | int i = 0, j = 0; 138 | unsigned char a, b; 139 | 140 | for(i = 0; i < len; i++){ 141 | a = (unsigned char)h1[i]; 142 | b = (unsigned char)h2[i]; 143 | #if 1 144 | for(j = 0; j < 8; j++){ 145 | if((a & 0x01) != (b & 0x01)){ 146 | return 0; 147 | } 148 | 149 | a = a >> 1; 150 | b = b >> 1; 151 | }// for 152 | #else 153 | if (a != b) { 154 | return 0; 155 | }// if 156 | #endif 157 | }// for 158 | 159 | return 1; 160 | } 161 | 162 | void printHash(unsigned char *hash,int len) 163 | { 164 | int i=0; 165 | 166 | while ( i - "); 241 | fflush(stdout); 242 | } 243 | 244 | int main(int argc, char *argv[]) 245 | { 246 | struct sockaddr_in sin, from, sout; 247 | struct ifreq ifr; 248 | int fd_tunnel, fd_udp, fd_tcp, fromlen, soutlen, port, PORT, l; 249 | char c, *p, *ip; 250 | fd_set fdset; 251 | int outl = sizeof(out); 252 | int cliserv = -1; /* must be specified on cmd line */ 253 | int flags = IFF_TUN; /* default */ 254 | char if_name[IFNAMSIZ] = ""; 255 | int i; 256 | int fds[2]; 257 | pid_t pid; 258 | 259 | /* initialize random seed */ 260 | srand(time(NULL)); 261 | 262 | progname = argv[0]; 263 | 264 | while ((c = getopt(argc, argv, "s:c:ehd")) != -1) { 265 | switch (c) { 266 | case 'h': 267 | usage(); 268 | case 'd': 269 | DEBUG++; 270 | break; 271 | case 's': 272 | cliserv = SERVER; 273 | PORT = atoi(optarg); 274 | break; 275 | case 'c': 276 | cliserv = CLIENT; 277 | p = memchr(optarg,':',16); 278 | if (!p) ERROR("invalid argument : [%s]\n",optarg); 279 | *p = 0; 280 | ip = optarg; 281 | port = atoi(p+1); 282 | PORT = 0; 283 | break; 284 | case 'e': 285 | flags = IFF_TAP; 286 | break; 287 | default: 288 | usage(); 289 | }//switch 290 | }//while 291 | if (cliserv < 0) usage(); 292 | 293 | /* Establish the Tunnel connection */ 294 | if ((fd_tunnel = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open"); 295 | 296 | memset(&ifr, 0, sizeof(ifr)); 297 | ifr.ifr_flags = flags; 298 | strncpy(ifr.ifr_name, "toto%d", IFNAMSIZ); 299 | if (ioctl(fd_tunnel, TUNSETIFF, (void *)&ifr) < 0) PERROR("ioctl"); 300 | 301 | printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name); 302 | 303 | /* Establish the UDP Network connection */ 304 | fd_udp = socket(PF_INET, SOCK_DGRAM, 0); 305 | sin.sin_family = AF_INET; 306 | sin.sin_addr.s_addr = htonl(INADDR_ANY); 307 | sin.sin_port = htons(PORT); 308 | if (bind(fd_udp,(struct sockaddr *)&sin, sizeof(sin)) < 0) PERROR("UDP-bind"); 309 | 310 | /* Establish the TCP Network connection */ 311 | fd_tcp = socket(PF_INET, SOCK_STREAM, 0); 312 | sin.sin_family = AF_INET; 313 | sin.sin_addr.s_addr = htonl(INADDR_ANY); 314 | sin.sin_port = htons(PORT); 315 | if (bind(fd_tcp,(struct sockaddr *)&sin, sizeof(sin)) < 0) PERROR("TCP-bind"); 316 | 317 | if (cliserv == CLIENT) { 318 | /* CLIENT */ 319 | int err = -1; 320 | int sd = -1; 321 | struct sockaddr_in sa; 322 | int salen = sizeof(sa); 323 | SSL_CTX* ctx = NULL; 324 | SSL* ssl = NULL; 325 | X509* server_cert; 326 | char* str = NULL; 327 | SSL_METHOD *meth = SSLv23_client_method(); //SSLv2_client_method(); 328 | char input; 329 | int cnValid = 0; 330 | int keyValid = 0; 331 | int ivValid = 0; 332 | int poke_count = 0; 333 | 334 | /* Create a pipe with two ends of pipe placed in fds[2], read_end=0, write_end=1 */ 335 | pipe(fds); 336 | /* Fork a child process */ 337 | pid = fork(); 338 | if (pid > (pid_t) 0) { /* TCP/SSL get Keys */ 339 | /* Client-Parent process */ 340 | 341 | /* close our copy of the read end of pipe */ 342 | close(fds[0]); 343 | 344 | /* Display startup message */ 345 | printf("MiniVPN Client...\n"); 346 | 347 | /* Output menu of choices */ 348 | displayClientMenu(); 349 | fflush(stdout); 350 | 351 | while(1) { 352 | /* Wait for TCP or user to make choice */ 353 | FD_ZERO(&fdset); 354 | FD_SET(STDIN_FILENO,&fdset); 355 | FD_SET(fd_tcp,&fdset); 356 | if (select(STDIN_FILENO+fd_tcp+1,&fdset,NULL,NULL,NULL) < 0) PERROR("Client-Parent select"); 357 | if (FD_ISSET(fd_tcp, &fdset)) { 358 | if (ssl) { 359 | /* Process POKE from Server */ 360 | if (DEBUG) printf("Client Waiting on Server... "); 361 | err = SSL_read(ssl,pokemsg,sizeof(pokemsg)-1); 362 | if (!strncmp(pokemsg,"POKE",4)) { 363 | if (DEBUG) printf("Received '%s', ",pokemsg); 364 | if (DEBUG) printf("Sending POKE_ACK, #pokes=%d\n",poke_count++); 365 | err = SSL_write(ssl,"POKE_ACK",strlen("POKE_ACK")); 366 | if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 367 | }//if 368 | else if (-1 == err) { 369 | PERROR("Client-Parent select"); 370 | }//else if 371 | }//if ssl 372 | }//if fd_tcp 373 | if (FD_ISSET(STDIN_FILENO, &fdset)) { 374 | /* Notify the child process to STOP send/receive packets */ 375 | strcpy(msg,"STOP"); 376 | write(fds[1],msg,strlen(msg)+1); 377 | SLEEP(1); 378 | 379 | /* Close down current SSL session */ 380 | printf("Clearing SSL session... "); 381 | /* send SSL/TLS close_notify */ 382 | if (NULL != ssl) SSL_shutdown(ssl); 383 | /* Clean up. */ 384 | if (sd >= 0) {close (sd); sd = -1;} 385 | if (NULL != ssl) {SSL_free(ssl); ssl = NULL;} 386 | if (NULL != ctx) {SSL_CTX_free(ctx); ctx = NULL;} 387 | poke_count = 0; 388 | printf("Done\n"); 389 | SLEEP(1); 390 | 391 | /* Get User Choice */ 392 | input = getch(); 393 | 394 | /* Process User Choice */ 395 | if ('k' == tolower(input)) { 396 | printf("\nKEY option..."); 397 | printf("\nEnter CommonName(CN)\n"); 398 | printf(">"); 399 | fflush(stdout); 400 | memset(szCommonName,0,sizeof(szCommonName)); 401 | scanf("%s",szCommonName); 402 | printf("\nEnter KEY\n"); 403 | printf("[--------------------------------]\n"); 404 | printf(">"); 405 | fflush(stdout); 406 | memset(msg,0,sizeof(msg)); 407 | scanf("%s",msg); 408 | memset(KEY,0,sizeof(KEY)); 409 | strncpy(KEY,msg,MAX_KEY_LENGTH); 410 | }//if 411 | else if ('i' == tolower(input)) { 412 | printf("\nIV option..."); 413 | printf("\nEnter CommonName(CN)\n"); 414 | printf(">"); 415 | fflush(stdout); 416 | memset(szCommonName,0,sizeof(szCommonName)); 417 | scanf("%s",szCommonName); 418 | printf("\nEnter IV (%d numbers)\n",IV_LENGTH); 419 | printf("[----------------]\n"); 420 | printf(">"); 421 | fflush(stdout); 422 | for (i=0; i"); 429 | fflush(stdout); 430 | memset(szCommonName,0,sizeof(szCommonName)); 431 | scanf("%s",szCommonName); 432 | printf("Random KEY and IV are being generated... "); 433 | /* Randomly generate ... KEY, IV */ 434 | memset(KEY,0,sizeof(KEY)); 435 | randomizeString(KEY,sizeof(KEY)-1); 436 | randomizeArray(IV,sizeof(IV)); 437 | printf("Done\n"); 438 | }//else if 439 | else if ('c' == tolower(input)) { 440 | /* Close down current SSL session */ 441 | printf("Clearing SSL session... "); 442 | /* send SSL/TLS close_notify */ 443 | if (NULL != ssl) SSL_shutdown(ssl); 444 | /* Clean up. */ 445 | if (sd >= 0) {close (sd); sd = -1;} 446 | if (NULL != ssl) {SSL_free(ssl); ssl = NULL;} 447 | if (NULL != ctx) {SSL_CTX_free(ctx); ctx = NULL;} 448 | poke_count = 0; 449 | printf("Done\n"); 450 | SLEEP(1); 451 | continue; 452 | }//else if 453 | else if ('s' == tolower(input)) { 454 | printf("\nClosing Tunnel... "); 455 | close(fd_tunnel); 456 | printf("Cleanup Done\n"); 457 | printf("GoodBye\n"); 458 | printf("Killing process tree\n"); 459 | SLEEP(1); 460 | killpg(getpgid(getpid()),SIGTERM); /* Kill the complete process tree including child. */ 461 | SLEEP(2); 462 | printf("Press Control-C to terminate\n"); 463 | while(1); 464 | }//else if 465 | else { 466 | /* Output menu of choices */ 467 | displayClientMenu(); 468 | 469 | continue; 470 | }//else 471 | 472 | /* Echo back to the user the CN + KEY + IV being used */ 473 | if (DEBUG) printf("CN is: [%s]\n",szCommonName); 474 | if (DEBUG) printf("KEY is: [%s]\n",KEY); 475 | if (DEBUG) {printf("IV is: ["); dumpBuf(IV,IV_LENGTH); printf("]\n\n");} 476 | 477 | if (DEBUG) printf("Session: ctx=%p, ssl=%p, sd=%d\n",ctx,ssl,sd); 478 | 479 | /* PKI: Authenticate the Server */ 480 | if (!ctx || !ssl || (sd < 0)) { 481 | if (DEBUG) printf("PKI: Authenticating the Server...\n"); 482 | SSLeay_add_ssl_algorithms(); 483 | SSL_load_error_strings(); 484 | ctx = SSL_CTX_new(meth); 485 | if (NULL == ctx) {if (DEBUG) printf("ctx error\n");err=-1;continue;}; 486 | 487 | SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); 488 | SSL_CTX_load_verify_locations(ctx,CCACERT,NULL); 489 | 490 | if (SSL_CTX_use_certificate_file(ctx,CCERTF,SSL_FILETYPE_PEM)<=0){ 491 | ERR_print_errors_fp(stderr);err=-2;continue;} 492 | if (SSL_CTX_use_PrivateKey_file(ctx,CKEYF,SSL_FILETYPE_PEM) <=0){ 493 | ERR_print_errors_fp(stderr);err=-3;continue;} 494 | if (!SSL_CTX_check_private_key(ctx)){ 495 | printf("Private key doesn't match cert. public key\n");err=-4;continue;} 496 | 497 | /* Create a socket and connect to server using normal socket calls. */ 498 | sd = socket (AF_INET, SOCK_STREAM, 0); 499 | if (-1 == sd) {perror("socket");err=-5;continue;} 500 | 501 | memset(&sa,0,sizeof(sa)); 502 | sa.sin_family = AF_INET; 503 | inet_aton(ip, &sa.sin_addr); /* Server IP */ 504 | sa.sin_port = htons(port); /* Server Port */ 505 | 506 | err = connect(sd,(struct sockaddr*)&sa,sizeof(sa)); 507 | if (-1 == err) {perror("connect");err=-6;continue;} 508 | 509 | /* Now we have TCP connection. Start SSL negotiation. */ 510 | ssl = SSL_new(ctx); if (NULL == ssl) {printf("TCP connect failure\n");err=-7;continue;} 511 | SSL_set_fd(ssl,sd); 512 | err = SSL_connect(ssl); if (-1 == err) {ERR_print_errors_fp(stderr);err=-8;continue;}; 513 | 514 | /* Following two steps are optional and not required for data exchange to be successful. */ 515 | 516 | /* Get the cipher - opt */ 517 | if (DEBUG) printf("SSL connection using %s\n",SSL_get_cipher(ssl)); 518 | 519 | /* Get server's certificate (note: beware of dynamic allocation) - opt */ 520 | server_cert = SSL_get_peer_certificate(ssl); 521 | if (NULL == server_cert){err=-9;continue;} 522 | if (DEBUG) printf("Server certificate:\n"); 523 | 524 | str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0); 525 | if (NULL == str){err=-10;continue;} 526 | //if (subjectstr) strcpy(subjectstr,str); 527 | if (DEBUG) printf("\t subject: %s\n",str); 528 | OPENSSL_free(str); 529 | 530 | str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0); 531 | if (NULL == str){err=-11;continue;} 532 | //if (issuerstr) strcpy(issuerstr,str); 533 | if (DEBUG) printf("\t issuer: %s\n",str); 534 | OPENSSL_free(str); 535 | 536 | /* We can do all sorts of certificate verification stuff here before 537 | deallocating the certificate. */ 538 | X509_free(server_cert); 539 | }//if 540 | 541 | /* DATA EXCHANGE AREA */ 542 | if (ssl) { 543 | /* Write CommonName (CN) to Server */ 544 | if (DEBUG) printf("Writing CN [%s] to Server\n",szCommonName); 545 | strcpy(msg,"CN:"); 546 | strcat(msg,szCommonName); 547 | err = SSL_write(ssl,msg,strlen(msg)); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 548 | /* Read CN reply from Server */ 549 | err = SSL_read(ssl,msg,sizeof(msg)-1); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 550 | msg[err] = '\0'; 551 | if (DEBUG) printf("Server replied with %d chars:'%s'\n",err,msg); 552 | if (strncmp(msg,"CN_ACK",6)) {cnValid=0;printf("Client_CN_ACK_Error\n");} 553 | else cnValid=1; 554 | 555 | /* Write KEY to Server */ 556 | if (DEBUG) printf("Writing KEY [%s] to Server\n",KEY); 557 | strcpy(msg,"KEY:"); 558 | strcat(msg,KEY); 559 | err = SSL_write(ssl,msg,strlen(msg)); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 560 | /* Read KEY reply from Server */ 561 | err = SSL_read(ssl,msg,sizeof(msg)-1); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 562 | msg[err] = '\0'; 563 | if (DEBUG) printf("Server replied with %d chars:'%s'\n",err,msg); 564 | if (strncmp(msg,"KEY_ACK",7)) {keyValid=0;printf("Client_KEY_ACK_Error\n");} 565 | else keyValid=1; 566 | 567 | /* Write IV to Server */ 568 | if (DEBUG) {printf("Writing IV ["); dumpBuf(IV,IV_LENGTH); printf("] to Server\n");} 569 | strcpy(msg,"IV:"); 570 | memcpy(&msg[3],&IV,sizeof(IV)); 571 | err = SSL_write(ssl,msg,3+sizeof(IV)); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 572 | /* Read IV reply from Server */ 573 | err = SSL_read(ssl,msg,sizeof(msg)-1); if (-1 == err) {ERR_print_errors_fp(stderr); continue;} 574 | msg[err] = '\0'; 575 | if (DEBUG) printf("Server replied with %d chars:'%s'\n",err,msg); 576 | if (strncmp(msg,"IV_ACK",6)) {ivValid=0;printf("Client_IV_ACK_Error\n");} 577 | else ivValid=1; 578 | 579 | /* Configure Client-Child to enable tunnel */ 580 | if (cnValid && keyValid && ivValid) { 581 | /* Write KEY to the child process */ 582 | if (DEBUG) printf("Issuing KEY to Client-Child\n"); 583 | strcpy(msg,"KEY:"); 584 | strcat(msg,KEY); 585 | write(fds[1],msg,strlen(msg)+1); 586 | SLEEP(1); 587 | 588 | /* Write IV to the child process */ 589 | if (DEBUG) printf("Issuing IV to Client-Child\n"); 590 | strcpy(msg,"IV:"); 591 | memcpy(&msg[3],&IV,sizeof(IV)); 592 | write(fds[1],msg,3+sizeof(IV)); 593 | SLEEP(1); 594 | 595 | /* Initialize FROM to point to Server's ip:port */ 596 | memset(&from,0,sizeof(from)); 597 | fromlen = sizeof(from); 598 | from.sin_family = AF_INET; 599 | from.sin_port = htons(port); 600 | inet_aton(ip,&from.sin_addr); 601 | 602 | /* Write FROM to the child process */ 603 | if (DEBUG) printf("Informing Client-Child the server's UDP addr+port\n"); 604 | strcpy(msg,"FROM:"); 605 | memcpy(&msg[5],&from,sizeof(from)); 606 | write(fds[1],msg,5+sizeof(from)); 607 | SLEEP(1); 608 | 609 | /* Notify the child process to be ready to send/receive packets */ 610 | if (DEBUG) printf("Issuing START to Client-Child\n"); 611 | strcpy(msg,"START"); 612 | write(fds[1],msg,strlen(msg)+1); 613 | SLEEP(1); 614 | }//if 615 | }//if ssl 616 | }//else if STDIN_FILENO 617 | }//while 618 | }//if Client-PARENT 619 | else { /* UDP use keys */ 620 | /* Client-Child process */ 621 | int okToStart = 0; 622 | struct sockaddr_in from; 623 | 624 | /* close our copy of the write end of pipe */ 625 | close(fds[1]); 626 | 627 | /* Set unblock pipe read */ 628 | 629 | /* Tunnel connection */ 630 | 631 | /* Keep reading from fds[0], fd_udp, fd_tunnel */ 632 | 633 | /* If notification is not received, do not send/receive */ 634 | 635 | /* while(true){if (read(fds[0]) == "start") break;} */ 636 | 637 | /* while(true){select from fd_udp and fd_tunnel, encryption/decryption, hash, sending/receiving packets} */ 638 | 639 | while (1) { 640 | FD_ZERO(&fdset); 641 | FD_SET(fds[0], &fdset); /* Pipe from Parent */ 642 | FD_SET(fd_tunnel,&fdset); /* Tunnel */ 643 | FD_SET(fd_udp, &fdset); /* Net-UDP */ 644 | if (select(fds[0]+fd_tunnel+fd_udp+1,&fdset,NULL,NULL,NULL) < 0) PERROR("Client-Child select"); 645 | if (FD_ISSET(fds[0], &fdset)) { 646 | memset(buf,0,sizeof(buf)); 647 | l = read(fds[0], buf, sizeof(buf)); 648 | if (l < 0) PERROR("read"); 649 | if (!strncmp(buf,"KEY:",4)) { 650 | if (DEBUG) printf("KEY: [%s] received from Client-Parent\n",&buf[4]); 651 | strncpy(KEY,&buf[4],sizeof(KEY)); 652 | }//if 653 | else if (!strncmp(buf,"IV:",3)) { 654 | if (DEBUG) {printf("IV: [");dumpBuf(&buf[3],sizeof(IV));printf("] received from Client-Parent\n",&buf[3]);} 655 | memcpy(IV,&buf[3],sizeof(IV)); 656 | }//else if 657 | else if (!strncmp(buf,"FROM:",5)) { 658 | if (DEBUG) printf("FROM: received from Client-Parent\n"); 659 | memcpy(&from,&buf[5],sizeof(from)); 660 | }//else if 661 | else if (!strncmp(buf,"START",5)) { 662 | if (DEBUG) printf("START received from Client-Parent\n"); 663 | okToStart = 1; 664 | /*if (DEBUG)*/ printf("Client Tunnel running...\n"); 665 | }//else if 666 | else if (!strncmp(buf,"STOP",4)) { 667 | if (DEBUG) printf("STOP received from Client-Parent\n"); 668 | okToStart = 0; 669 | /*if (DEBUG)*/ printf("Client Tunnel stopped\n"); 670 | }//else if 671 | else okToStart = 0; 672 | }//if 673 | else if (FD_ISSET(fd_tunnel, &fdset)) { 674 | if (okToStart) { 675 | /* wait for data from tunnel, then encrypt+hash, then send to "remote/from" network socket */ 676 | if (DEBUG) write(1,">", 1); 677 | l = read(fd_tunnel, buf, sizeof(buf)); 678 | if (l < 0) PERROR("read"); 679 | else { 680 | if (DEBUG) {printf("\nTx=%d[",l); dumpBuf(buf,l); printf("]\n");} 681 | outl = sizeof(out); 682 | do_encrypt(buf,l,out,&outl); 683 | if (outl > MAX_BLOCK_LENGTH) PERROR("Encrypt Too Big"); 684 | if (DEBUG) {printf("\nEncrypt=%d[",outl); dumpBuf(out,outl); printf("]\n");} 685 | createHash(buf, l, md_value, &md_len); 686 | if ((outl + md_len) > MAX_BLOCK_LENGTH) PERROR("Encrypt+Hash Too Big"); 687 | if (DEBUG) {printf("Hash=%d[",md_len); dumpBuf(md_value,md_len); printf("]\n");} 688 | for (i=0; i (pid_t) 0) { /* TCP get Keys */ 784 | /* Server-Parent process */ 785 | 786 | /* close our copy of the read end of pipe */ 787 | close(fds[0]); 788 | 789 | /* Display startup message */ 790 | printf("MiniVPN Server...\n"); 791 | fflush(stdout); 792 | 793 | while(1) { 794 | FD_ZERO(&fdset); 795 | FD_SET(fd_tcp,&fdset); 796 | FD_SET(timer_fd,&fdset); 797 | if (select(fd_tcp+timer_fd+1,&fdset,NULL,NULL,NULL) < 0) PERROR("Server-Parent select"); 798 | if (FD_ISSET(timer_fd, &fdset)) { 799 | int s; 800 | uint64_t exp; 801 | s = read(timer_fd, &exp, sizeof(uint64_t)); 802 | 803 | /* Reset time-interval in case altered */ 804 | time_period.it_interval.tv_sec = POKE_INTERVAL_IN_SECS; 805 | time_period.it_interval.tv_nsec = 0; 806 | time_period.it_value.tv_sec = POKE_INTERVAL_IN_SECS; 807 | time_period.it_value.tv_nsec = 0; 808 | 809 | /* Is SSL connection currently active with Client? */ 810 | if (ssl) { 811 | /* POKE_Client via SSL*/ 812 | if (DEBUG) printf("Server POKE Client, Waiting... "); 813 | err = SSL_write(ssl,"POKE",strlen("POKE")); 814 | memset(pokemsg,0,sizeof(pokemsg)); 815 | err = SSL_read(ssl,pokemsg,sizeof(msg)-1); 816 | if ((-1 == err) || (strncmp(pokemsg,"POKE_ACK",8))) 817 | { 818 | /* Client did not respond -OR- invalid reponse */ 819 | if (err >= 0) { 820 | pokemsg[err] = '\0'; 821 | if (DEBUG) printf("Received '%s'\n",pokemsg); 822 | }//if 823 | else { 824 | if (DEBUG) printf("Timeout\n"); 825 | }//else 826 | 827 | if (DEBUG) printf("Closing SSL connection with Client\n"); 828 | 829 | /* Close SSL connection with Client. */ 830 | if (sd >= 0) {close(sd); sd = -1;} 831 | if (NULL != ssl) {SSL_free(ssl); ssl = NULL;} 832 | if (NULL != ctx) {SSL_CTX_free(ctx); ctx = NULL;} 833 | 834 | poke_count = 0; 835 | 836 | /* Notify the child process to STOP send/receive packets */ 837 | strcpy(pokemsg,"STOP"); 838 | write(fds[1],pokemsg,strlen(pokemsg)+1); 839 | }//if disconnect Client 840 | else { 841 | pokemsg[err] = '\0'; 842 | if (DEBUG) printf("Received '%s', #pokes=%d\n",pokemsg,poke_count++); 843 | }//else 844 | }//if ssl 845 | }//if timer_fd 846 | if (FD_ISSET(fd_tcp, &fdset)) { 847 | /* Notify the child process to STOP send/receive packets */ 848 | strcpy(msg,"STOP"); 849 | write(fds[1],msg,strlen(msg)+1); 850 | SLEEP(1); 851 | 852 | if (DEBUG) printf("Session: ctx=%p, ssl=%p, sd=%d\n",ctx,ssl,sd); 853 | 854 | /* PKI: Authenticate the Client */ 855 | if (!ctx || !ssl || (sd < 0)) { 856 | if (DEBUG) printf("PKI: Authenticating the Client...\n"); 857 | 858 | /* SSL preliminaries. We keep the certificate and key with the context. */ 859 | SSLeay_add_ssl_algorithms(); 860 | SSL_load_error_strings(); 861 | ctx = SSL_CTX_new (meth); 862 | if (!ctx) {ERR_print_errors_fp(stderr);err=-1;continue;} 863 | 864 | SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /* whether verify the certificate */ 865 | SSL_CTX_load_verify_locations(ctx,SCACERT,NULL); 866 | 867 | if (SSL_CTX_use_certificate_file(ctx,SCERTF,SSL_FILETYPE_PEM)<=0){ 868 | ERR_print_errors_fp(stderr);err=-2;continue;} 869 | if (SSL_CTX_use_PrivateKey_file(ctx,SKEYF,SSL_FILETYPE_PEM) <=0){ 870 | ERR_print_errors_fp(stderr);err=-3;continue;} 871 | if (!SSL_CTX_check_private_key(ctx)){ 872 | fprintf(stderr,"Private key does not match the certificate public key\n");err=-4;continue;} 873 | 874 | /* Prepare TCP socket for receiving connections */ 875 | //listen_sd = socket(AF_INET,SOCK_STREAM,0); 876 | if (-1 == listen_sd) {perror("socket");err=-5;continue;} 877 | 878 | //memset(&sa_serv,0,sizeof(sa_serv)); 879 | //sa_serv.sin_family = AF_INET; 880 | //sa_serv.sin_addr.s_addr = INADDR_ANY; 881 | //sa_serv.sin_port = htons(PORT); /* Server Port number */ 882 | 883 | //err = bind(listen_sd,(struct sockaddr*)&sa_serv,sizeof(sa_serv)); 884 | //if (-1 == err) {perror("bind");err=-6;continue;} 885 | 886 | /* Receive a TCP connection. */ 887 | err = listen(listen_sd,5); 888 | if (-1 == err) {perror("listen");err=-7;continue;} 889 | 890 | client_len = sizeof(sa_cli); 891 | sd = accept(listen_sd,(struct sockaddr*)&sa_cli,&client_len); 892 | if (-1 == sd) {perror("accept");err=-8;continue;} 893 | //close(listen_sd); 894 | 895 | //if (DEBUG) printf("Connection from %lx, port %d\n",sa_cli.sin_addr.s_addr,sa_cli.sin_port); 896 | if (DEBUG) printf("Connection from ip:port %s:%i established\n", 897 | inet_ntoa(sa_cli.sin_addr/*.s_addr*/),ntohs(sa_cli.sin_port)); 898 | 899 | /* TCP connection is ready. Do server side SSL. */ 900 | ssl = SSL_new(ctx); if (NULL == ssl) {printf("TCP connect failure\n");err=-9;continue;} 901 | SSL_set_fd(ssl,sd); 902 | err = SSL_accept(ssl); if (-1 == err) {ERR_print_errors_fp(stderr);err=-10;continue;} 903 | 904 | /* Get the cipher - opt */ 905 | if (DEBUG) printf("SSL connection using %s\n",SSL_get_cipher(ssl)); 906 | 907 | /* Get client's certificate (note: beware of dynamic allocation) - opt */ 908 | client_cert = SSL_get_peer_certificate(ssl); 909 | if (NULL == client_cert) {printf("Client does not have certificate.\n");err=-11;continue;} 910 | if (DEBUG) printf("Client certificate:\n"); 911 | 912 | str = X509_NAME_oneline(X509_get_subject_name(client_cert),0,0); 913 | if (NULL == str) {err=-12;continue;} 914 | strncpy(subjectstr,str,sizeof(subjectstr)-1); 915 | if (DEBUG) printf("\t subject: %s\n",str); 916 | OPENSSL_free(str); 917 | 918 | str = X509_NAME_oneline(X509_get_issuer_name(client_cert),0,0); 919 | if (NULL == str) {err=-13;continue;} 920 | strncpy(issuerstr,str,sizeof(issuerstr)-1); 921 | if (DEBUG) printf("\t issuer: %s\n",str); 922 | OPENSSL_free(str); 923 | 924 | /* We can do all sorts of certificate verification stuff here before 925 | deallocating the certificate. */ 926 | X509_free (client_cert); 927 | }//if 928 | 929 | /* DATA EXCHANGE - Receive messages and send replies */ 930 | if (ssl) { 931 | /* Read CN from Client */ 932 | err = SSL_read(ssl,msg,sizeof(msg)-1); 933 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-14;continue;} 934 | msg[err] = '\0'; 935 | if (DEBUG) printf("Received from Client %d chars:'%s'\n",err,msg); 936 | /* Audit CN from Client */ 937 | cnValid = 0; 938 | if (!strncmp(msg,"CN:",3)) { 939 | char *pch_start = strstr(subjectstr,"/CN="); 940 | if (NULL != pch_start) { 941 | char *pch_end = strstr(&pch_start[1],"/"); 942 | if (NULL != pch_end) { 943 | int cn_len = (int)pch_end - (int)&pch_start[4]; 944 | if (!strncmp(&pch_start[4],&msg[3],cn_len)) { 945 | cnValid=1; 946 | }//if 947 | }//if 948 | }//if 949 | }//if 950 | /* Write CN reply to Client */ 951 | if (1 == cnValid) { 952 | err = SSL_write(ssl,"CN_ACK",strlen("CN_ACK")); 953 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-15;continue;} 954 | }//if 955 | else { 956 | err = SSL_write(ssl,"CN_NACK",strlen("CN_NACK")); 957 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-16;continue;} 958 | }//else 959 | 960 | /* Read KEY from Client */ 961 | err = SSL_read(ssl,msg,sizeof(msg)-1); 962 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-17;continue;} 963 | msg[err] = '\0'; 964 | if (DEBUG) printf("Received from Client %d chars:'%s'\n",err,msg); 965 | /* Write KEY reply to Client */ 966 | if (!strncmp(msg,"KEY:",4)) { 967 | strncpy(KEY,&msg[4],MAX_KEY_LENGTH); 968 | keyValid=1; 969 | err = SSL_write(ssl,"KEY_ACK",strlen("KEY_ACK")); 970 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-18;continue;} 971 | }//if 972 | else { 973 | keyValid=0; 974 | err = SSL_write(ssl,"KEY_NACK",strlen("KEY_NACK")); 975 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-19;continue;} 976 | }//else 977 | 978 | /* Read IV from Client */ 979 | err = SSL_read(ssl,msg,sizeof(msg)-1); 980 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-20;continue;} 981 | msg[err] = '\0'; 982 | if (DEBUG) {printf("Received from Client %d chars:'%c%c%c",err,msg[0],msg[1],msg[2]); 983 | dumpBuf(&msg[3],err-3);printf("'\n");} 984 | /* Write IV reply to Client */ 985 | if (!strncmp(msg,"IV:",3)) { 986 | memcpy(IV,&msg[3],IV_LENGTH); 987 | ivValid=1; 988 | err = SSL_write(ssl,"IV_ACK",strlen("IV_ACK")); 989 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-21;continue;} 990 | }//if 991 | else { 992 | ivValid=0; 993 | err = SSL_write(ssl,"IV_NACK",strlen("IV_NACK")); 994 | if (-1 == err) {ERR_print_errors_fp(stderr);err=-22;continue;} 995 | }//else 996 | 997 | #if 0 998 | /* Clean up. */ 999 | if (sd >= 0) {close(sd); sd = -1;} 1000 | if (NULL != ssl) {SSL_free(ssl); ssl = NULL;} 1001 | if (NULL != ctx) {SSL_CTX_free(ctx); ctx = NULL;} 1002 | #endif 1003 | 1004 | if (cnValid && keyValid && ivValid) { 1005 | /* Write KEY to the child process */ 1006 | strcpy(msg,"KEY:"); 1007 | strcat(msg,KEY); 1008 | write(fds[1],msg,strlen(msg)+1); 1009 | SLEEP(1); 1010 | 1011 | /* Write IV to the child process */ 1012 | strcpy(msg,"IV:"); 1013 | memcpy(&msg[3],&IV,sizeof(IV)); 1014 | write(fds[1],msg,3+sizeof(IV)); 1015 | SLEEP(1); 1016 | 1017 | /* Initialize FROM to point to Client's ip:port */ 1018 | memset(&from,0,sizeof(from)); 1019 | fromlen = sizeof(from); 1020 | from = sa_cli; 1021 | 1022 | /* Write FROM to the child process */ 1023 | strcpy(msg,"FROM:"); 1024 | memcpy(&msg[5],&from,sizeof(from)); 1025 | write(fds[1],msg,5+sizeof(from)); 1026 | SLEEP(1); 1027 | 1028 | /* Notify the child process to be ready to send/receive packets */ 1029 | strcpy(msg,"START"); 1030 | write(fds[1],msg,strlen(msg)+1); 1031 | SLEEP(1); 1032 | }//if VALID 1033 | }// ssl 1034 | }//else if TCP 1035 | }// while 1036 | }// if Server-PARENT 1037 | else { /* UDP use keys */ 1038 | /* Server-Child process */ 1039 | int okToStart = 0; 1040 | struct sockaddr_in from; 1041 | 1042 | /* close our copy of the write end of pipe */ 1043 | close(fds[1]); 1044 | 1045 | /* Set unblock pipe read */ 1046 | 1047 | /* Tunnel connection */ 1048 | 1049 | /* Keep reading from fds[0], fd_udp, fd_tunnel */ 1050 | 1051 | /* If notification is not received, do not send/receive */ 1052 | 1053 | while (1) { 1054 | FD_ZERO(&fdset); 1055 | FD_SET(fds[0], &fdset); /* Pipe from Parent */ 1056 | FD_SET(fd_tunnel,&fdset); /* Tunnel */ 1057 | FD_SET(fd_udp, &fdset); /* Net-UDP */ 1058 | if (select(fds[0]+fd_tunnel+fd_udp+1,&fdset,NULL,NULL,NULL) < 0) PERROR("Server-Child select"); 1059 | if (FD_ISSET(fds[0], &fdset)) { 1060 | memset(buf,0,sizeof(buf)); 1061 | l = read(fds[0], buf, sizeof(buf)); 1062 | if (l < 0) PERROR("read"); 1063 | if (!strncmp(buf,"KEY:",4)) { 1064 | if (DEBUG) printf("KEY: [%s] received from Server-Parent\n",&buf[4]); 1065 | strncpy(KEY,&buf[4],sizeof(KEY)); 1066 | }//if 1067 | else if (!strncmp(buf,"IV:",3)) { 1068 | if (DEBUG) { 1069 | printf("IV: ["); 1070 | dumpBuf(&buf[3],sizeof(IV)); 1071 | printf("] received from Server-Parent\n",&buf[3]); 1072 | }//if 1073 | memcpy(IV,&buf[3],sizeof(IV)); 1074 | }//else if 1075 | else if (!strncmp(buf,"FROM:",5)) { 1076 | if (DEBUG) printf("FROM: received from Server-Parent\n"); 1077 | memcpy(&from,&buf[5],sizeof(from)); 1078 | }//else if 1079 | else if (!strncmp(buf,"START",5)) { 1080 | if (DEBUG) printf("START received from Server-Parent\n"); 1081 | okToStart = 1; 1082 | /*if (DEBUG)*/ printf("Server Tunnel running...\n"); 1083 | }//else if 1084 | else if (!strncmp(buf,"STOP",4)) { 1085 | if (DEBUG) printf("STOP received from Server-Parent\n"); 1086 | okToStart = 0; 1087 | /*if (DEBUG)*/ printf("Server Tunnel stopped\n"); 1088 | }//else if 1089 | else okToStart = 0; 1090 | }//if 1091 | else if (FD_ISSET(fd_tunnel, &fdset)) { 1092 | if (okToStart) { 1093 | /* wait for data from tunnel, then encrypt+hash, then send to "remote/from" network socket */ 1094 | if (DEBUG) write(1,">", 1); 1095 | l = read(fd_tunnel, buf, sizeof(buf)); 1096 | if (l < 0) PERROR("read"); 1097 | else { 1098 | if (DEBUG) {printf("\nTx=%d[",l); dumpBuf(buf,l); printf("]\n");} 1099 | outl = sizeof(out); 1100 | do_encrypt(buf,l,out,&outl); 1101 | if (outl > MAX_BLOCK_LENGTH) PERROR("Encrypt Too Big"); 1102 | if (DEBUG) {printf("\nEncrypt=%d[",outl); dumpBuf(out,outl); printf("]\n");} 1103 | createHash(buf, l, md_value, &md_len); 1104 | if ((outl + md_len) > MAX_BLOCK_LENGTH) PERROR("Encrypt+Hash Too Big"); 1105 | if (DEBUG) {printf("Hash=%d[",md_len); dumpBuf(md_value,md_len); printf("]\n");} 1106 | for (i=0; i