1/* 2 * LICENSE NOTICE. 3 * 4 * Use of the Microsoft Windows Rally Development Kit is covered under 5 * the Microsoft Windows Rally Development Kit License Agreement, 6 * which is provided within the Microsoft Windows Rally Development 7 * Kit or at http://www.microsoft.com/whdc/rally/rallykit.mspx. If you 8 * want a license from Microsoft to use the software in the Microsoft 9 * Windows Rally Development Kit, you must (1) complete the designated 10 * "licensee" information in the Windows Rally Development Kit License 11 * Agreement, and (2) sign and return the Agreement AS IS to Microsoft 12 * at the address provided in the Agreement. 13 */ 14 15/* 16 * Copyright (c) Microsoft Corporation 2005. All rights reserved. 17 * This software is provided with NO WARRANTY. 18 */ 19 20//#define CHECKING_PACKING 1 21 22#define _GNU_SOURCE 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <unistd.h> 27#include <assert.h> 28 29#define DECLARING_GLOBALS 30#include "globals.h" 31 32#include "statemachines.h" 33#include "packetio.h" 34 35extern void qos_init(void); 36 37bool_t isConfTest; 38 39static void 40usage(void) 41{ 42 fprintf(stderr, "usage: %s [-d] [-t TRACELEVEL] INTERFACE [WIRELESS-IF]\n" 43 "\tRuns a link-layer topology discovery daemon on INTERFACE (eg eth0)\n" 44 "\t-d : don't background, and log moderate tracing to stdout (debug mode)\n" 45 "\t-t TRACELEVEL : select tracing by adding together:\n" 46 "\t\t0x01 : BAND network load control calculations\n" 47 "\t\t0x02 : packet dump of protocol exchange\n" 48 "\t\t0x04 : Charge mechanism for protection against denial of service\n" 49 "\t\t0x08 : system information TLVs (type-length-value)\n" 50 "\t\t0x10 : State-Machine transitions for smS, smE, and smT\n" 51 "\t\t0x20 : Qos/qWave extensions\n", 52 g_Progname); 53 exit(2); 54} 55 56 57static void 58init_from_conf_file() 59{ 60 FILE *conf_file; 61 char *line = NULL; 62 #define LINEBUFLEN 256 63 char var[LINEBUFLEN]; 64 char val[LINEBUFLEN]; 65 size_t len = 0; 66 ssize_t numread; 67 int assigns; 68 char default_icon_path[] = {"/etc/icon.ico"}; 69 70 /* Set default values for configuration options */ 71 /* (avoid strdup() since it doesn't use xmalloc wrapper) */ 72 g_icon_path = xmalloc(strlen(default_icon_path)+1); 73 strcpy(g_icon_path,default_icon_path); 74 75 /* Examine configuration file, if it exists */ 76 conf_file = fopen("/etc/lld2d.conf", "r"); 77 if (conf_file == NULL) return; 78 while ((numread = getline(&line, &len, conf_file)) != -1) 79 { 80 var[0] = val[0] = '\0'; 81 assigns = sscanf(line, "%s = %s", var, val); 82 83 if (assigns==2) 84 { 85 /* compare to each of the 2 allowed vars... */ 86 if (!strcmp(var,"icon")) { 87 char *path = NULL; 88 char *cur = NULL; 89 90 path = xmalloc(strlen(val)+6); // always allow enough room for a possible prefix of '/etc/' 91 cur = path; 92 93 /* Check for leading '/' and prefix '/etc/' if missing */ 94 if (val[0] != '/') 95 { 96 strcpy(cur,"/etc/"); cur += 5; 97 } 98 strncpy(cur,val,strlen(val)); 99 100 if (g_icon_path) xfree(g_icon_path); // always use the most recent occurrence 101 g_icon_path = path; 102 DEBUG({printf("configvar 'g_icon_path' = %s\n", g_icon_path);}) 103 } else if (!strcmp(var,"jumbo-icon")) { 104 char *path = NULL; 105 char *cur = NULL; 106 107 path = xmalloc(strlen(val)+6); // always allow enough room for a possible prefix of '/etc/' 108 cur = path; 109 110 /* Check for leading '/' and prefix '/etc/' if missing */ 111 if (val[0] != '/') 112 { 113 strcpy(cur,"/etc/"); cur += 5; 114 } 115 strncpy(cur,val,strlen(val)); 116 117 if (g_jumbo_icon_path) xfree(g_jumbo_icon_path); // always use the most recent occurrence 118 g_jumbo_icon_path = path; 119 DEBUG({printf("configvar 'g_jumbo_icon_path' = %s\n", g_jumbo_icon_path);}) 120 } else { 121 warn("line ignored - var does not match a known string\n"); 122 } 123 } else { 124 warn("line ignored - var or val was missing or no equals\n"); 125 } 126 127 } 128 if (line!=NULL) free(line); 129 fclose(conf_file); 130} 131 132//-----------------------------------------------------------------------------------------------------------// 133int 134main(int argc, char **argv) 135{ 136 char *p; 137 int c; 138 bool_t opt_debug = FALSE; 139 int opt_trace = 0; 140 141 /* set program name to last component of filename */ 142 p = strrchr(argv[0], '/'); 143 if (p) 144 g_Progname = p+1; 145 else 146 g_Progname = argv[0]; 147 148 /* set a module flag if this is the confidence test */ 149 isConfTest = (strstr(g_Progname,"conftest") != NULL ? TRUE : FALSE); 150 151 /* parse arguments */ 152 while ((c=getopt(argc, argv, "dt:")) != -1) 153 { 154 switch (c) 155 { 156 case 'd': 157 opt_debug = TRUE; 158 break; 159 160 case 't': 161 opt_trace = atoi(optarg); 162 if (opt_trace == 0) 163 { 164 fprintf(stderr, "%s: -t TRACELEVEL: parse error in \"%s\"\n", 165 g_Progname, optarg); 166 usage(); 167 } 168 break; 169 170 default: 171 if (isConfTest) 172 { 173 opt_debug = TRUE; 174 opt_trace = TRC_PACKET + TRC_STATE; 175 } else { 176 usage(); 177 } 178 break; 179 } 180 } 181 182 if (isConfTest) 183 { 184 if (optind >= argc) 185 { 186 g_interface = strstr(g_Progname,"x86") != NULL ? "eth0" : "br0"; 187 g_wl_interface = strstr(g_Progname,"x86") != NULL ? "eth0" : "eth1"; 188 printf("%s: no interface-name argument; '%s' assumed.\n", g_Progname, g_interface); 189 } else { 190 g_interface = strdup(argv[optind]); 191 if ((optind+1) >= argc) 192 { 193 g_wl_interface = g_interface; 194 } else { 195 g_wl_interface = strdup(argv[optind+1]); 196 } 197 } 198 } else { 199 if (optind >= argc) 200 { 201 fprintf(stderr, "%s: error: missing INTERFACE name argument\n", g_Progname); 202 usage(); 203 } else { 204 g_interface = strdup(argv[optind]); 205 if ((optind+1) >= argc) 206 { 207 g_wl_interface = g_interface; 208 } else { 209 g_wl_interface = strdup(argv[optind+1]); 210 } 211 } 212 } 213 214#ifdef CHECKING_PACKING 215 printf("etherHdr: " FMT_SIZET " baseHdr: " FMT_SIZET " discoverHdr: " \ 216 FMT_SIZET " helloHdr: " FMT_SIZET " qltlvHdr: " FMT_SIZET "\n", 217 sizeof(topo_ether_header_t),sizeof(topo_base_header_t),sizeof(topo_discover_header_t), 218 sizeof(topo_hello_header_t),sizeof(topo_qltlv_header_t)); 219 assert(sizeof(topo_ether_header_t) == 14); 220 assert(sizeof(topo_base_header_t) == 18); 221 assert(sizeof(topo_discover_header_t) == 4); 222 assert(sizeof(topo_hello_header_t) == 14); 223 assert(sizeof(topo_qltlv_header_t) == 4); 224 puts("Passed struct-packing checks!"); 225#endif 226 227 /* initialise remaining process state */ 228 g_trace_flags = opt_trace; 229 memset(&g_hwaddr,0,sizeof(etheraddr_t)); 230 231 g_smE_state = smE_Quiescent; 232 g_smT_state = smT_Quiescent; 233 234 memset (g_sessions,0,MAX_NUM_SESSIONS*sizeof(g_sessions[0])); 235 236 memset(&g_band,0,sizeof(band_t)); /* BAND algorthm's state */ 237 g_osl = osl_init(); /* initialise OS-glue Layer */ 238 memset(g_rxbuf,0,(size_t)RXBUFSZ); 239 memset(g_emitbuf,0,(size_t)RXBUFSZ); 240 memset(g_txbuf,0,(size_t)TXBUFSZ); 241 memset(g_re_txbuf,0,(size_t)TXBUFSZ); 242 g_sees = seeslist_new(NUM_SEES); 243 g_rcvd_pkt_len = 0; 244 g_rtxseqnum = 0; 245 g_re_tx_len = 0; 246 g_generation = 0; 247 g_sequencenum = 0; 248 g_opcode = Opcode_INVALID; 249 g_ctc_packets = 0; 250 g_ctc_bytes = 0; 251 252#if CAN_FOPEN_IN_SELECT_LOOP 253 /* then we don't need a global to keep the stream open all the time...*/ 254#else 255 g_procnetdev = fopen("/proc/net/dev","r"); 256 if (g_procnetdev<0) 257 die("fopen of /proc/net/dev failed\n"); 258#endif 259 260 /* Initialize the timers (inactivity timers are init'd when session is created) */ 261 g_block_timer = g_charge_timer = g_emit_timer = g_hello_timer = NULL; 262 263 /* initialize things from the parameter file, /etc/lld2d.conf 264 * currently, v1.0, this only involves LTLV pointers... */ 265 266 init_from_conf_file(); 267 268 event_init(); 269 qos_init(); 270 271 osl_interface_open(g_osl, g_interface, NULL); 272 osl_get_hwaddr(g_osl, &g_hwaddr); 273 274 IF_DEBUG 275 printf("%s: listening at address: " ETHERADDR_FMT "\n", 276 g_Progname, ETHERADDR_PRINT(&g_hwaddr)); 277 END_DEBUG 278 if (!opt_debug) 279 { 280 DEBUG({printf("%s: Using syslog\n", g_Progname);}) 281 util_use_syslog(); 282 DEBUG({printf("%s: Daemonizing...\n", g_Progname);}) 283 osl_become_daemon(g_osl); 284 } 285 DEBUG({printf("%s: listening on interface %s\n", g_Progname, g_interface);}) 286 287 osl_write_pidfile(g_osl); 288 289 osl_drop_privs(g_osl); 290 291 /* add IO handlers & run main event loop forever */ 292 event_mainloop(); 293 294 return 0; 295} 296