00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <sys/types.h>
00040 #include <sys/socket.h>
00041 #include <sys/ioctl.h>
00042 #include <sys/stat.h>
00043 #include <fcntl.h>
00044 #include <netinet/in.h>
00045 #include <arpa/inet.h>
00046 #include <net/if.h>
00047 #include <syslog.h>
00048 #include <signal.h>
00049 #include <pthread.h>
00050 #include <errno.h>
00051
00052 #include "sensor_self.h"
00053 #include "mesh_metrics.h"
00054 #include "mesh_discovery.h"
00055 #include "mesh_neighbor.h"
00056 #include "mesh_net.h"
00057 #include "mesh_ipc.h"
00058 #include "mesh_on_demand.h"
00059
00060 #ifdef DEBUG
00061 # include "sigsegv.h"
00062 #endif
00063
00064
00065 #define MESH_APPLICATION "sensormeshd"
00066 #define MESH_VERSION "0.3"
00067
00068 #define error(...) do { \
00069 fprintf(stderr, "%s (%s:%d) ", MESH_APPLICATION, __FUNCTION__, __LINE__); \
00070 fprintf(stderr, __VA_ARGS__); \
00071 fprintf(stderr, ".\n"); \
00072 } while (0)
00073
00074
00075 void *run_echo(void *arg)
00076 {
00077 self_t *self = (self_t*)arg;
00078 if (self == NULL)
00079 return NULL;
00080 echo_statistics(self);
00081 return NULL;
00082 }
00083
00084
00085 void *run_statistics(void *arg)
00086 {
00087 self_t *self = (self_t*)arg;
00088 if (self == NULL)
00089 return NULL;
00090 gather_statistics(self);
00091 return NULL;
00092 }
00093
00094
00095 void *run_controller(void *arg)
00096 {
00097 self_t *self = (self_t*)arg;
00098 if (self == NULL)
00099 return NULL;
00100 mesh_ioserv(self);
00101 return NULL;
00102 }
00103
00104
00105 void *discover_neighbors(void *arg)
00106 {
00107 self_t *self = (self_t*)arg;
00108 if (self == NULL)
00109 return NULL;
00110 neighbor_discovery(self);
00111 return NULL;
00112 }
00113
00114
00115 void *semi_reliability(void *arg)
00116 {
00117 self_t *self = (self_t*)arg;
00118 if (self == NULL)
00119 return NULL;
00120 reliable_net(self);
00121 return NULL;
00122 }
00123
00124
00125 void *start_on_demand(void *arg)
00126 {
00127 self_t *self = (self_t*)arg;
00128 if (self == NULL)
00129 return NULL;
00130 on_demand(self);
00131 return NULL;
00132 }
00133
00134
00135 void *on_demand_timeouts(void *arg)
00136 {
00137 self_t *self = (self_t*)arg;
00138 if (self == NULL)
00139 return NULL;
00140 packet_usage(self);
00141 return NULL;
00142 }
00143
00144
00145
00146
00147 static void daemonize(char *device)
00148 {
00149 int fd;
00150 struct sigaction sa;
00151
00152 if (setreuid(0, 0) < 0) {
00153 fprintf(stderr, "Root access required\n");
00154 exit(-1);
00155 }
00156
00157 if (fork())
00158 exit(0);
00159
00160 fd = open("/dev/null", O_RDWR);
00161 dup2(fd, 0); dup2(fd, 1); dup2(fd, 2);
00162 close(fd);
00163
00164 setsid();
00165 chdir("/");
00166
00167 openlog(MESH_APPLICATION, LOG_CONS | LOG_PID | LOG_NDELAY | LOG_PERROR,
00168 LOG_DAEMON);
00169 syslog(LOG_INFO, "%s v%s started on %s.",
00170 MESH_APPLICATION, MESH_VERSION, device);
00171
00172 memset(&sa, 0, sizeof(sa));
00173 sa.sa_handler = SIG_IGN;
00174 sigaction(SIGCHLD, &sa, NULL);
00175 }
00176
00177
00178 int main(int argc, char *argv[])
00179 {
00180 pthread_t stats, echo, control;
00181 int fd, i, rc;
00182 char *address = NULL;
00183 struct ifreq ifr;
00184 self_t myself;
00185 protocol_t *cur;
00186
00187 #ifdef DEBUG
00188 setup_sigsegv();
00189 #endif
00190 init_self(&myself);
00191
00192 if (argc < 2 || argc > 5) {
00193 usage:
00194 fprintf(stderr, "Usage: %s [-g] [-a address] [-p lat:lon:alt] interface\n",
00195 argv[0]);
00196 exit(-1);
00197 }
00198 for (i = 1; i < argc; i++) {
00199
00200 if (strncmp("-g", argv[i], 2) == 0)
00201 myself.isa_gateway = 1;
00202 if (strncmp("-a", argv[i], 2) == 0)
00203 address = argv[++i];
00204 if (strncmp("-p", argv[i], 2) == 0) {
00205 if (sscanf(argv[++i], "%lf:%lf:%lf",
00206 &myself.latitude, &myself.longitude, &myself.altitude) < 3)
00207 goto usage;
00208
00209 }
00210 else if (strcmp("", argv[i]) != 0)
00211 myself.interface = argv[i];
00212 }
00213 if (myself.interface == NULL) {
00214 error("no network interface given");
00215 exit(-1);
00216 }
00217
00218 fd = socket(PF_INET, SOCK_DGRAM, 0);
00219 strcpy(ifr.ifr_name, myself.interface);
00220
00221 if (address != NULL)
00222 strncpy(myself.ip_addr, address, NET_ADDR_LEN);
00223 else {
00224 ifr.ifr_addr.sa_family = AF_INET;
00225 if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
00226 error("network interface \"%s\" not found (%s)",
00227 myself.interface, strerror(errno));
00228 exit(-1);
00229 }
00230 strcpy(myself.ip_addr,
00231 inet_ntoa(((struct sockaddr_in*)(&ifr.ifr_addr))->sin_addr));
00232
00233 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0) {
00234 error("error retrieving broadcast address (%s)",
00235 strerror(errno));
00236 exit(-1);
00237 }
00238 strcpy(myself.broadcast,
00239 inet_ntoa(((struct sockaddr_in*)(&ifr.ifr_addr))->sin_addr));
00240
00241 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) {
00242 error("error retrieving netmask (%s)",
00243 strerror(errno));
00244 exit(-1);
00245 }
00246 strcpy(myself.netmask,
00247 inet_ntoa(((struct sockaddr_in*)(&ifr.ifr_addr))->sin_addr));
00248 }
00249 close(fd);
00250
00251 daemonize(myself.interface);
00252
00253 #ifdef DEBUG
00254 syslog(LOG_INFO, "configuration for %s: addr=%s, bcast=%s, netmask=%s",
00255 myself.interface, myself.ip_addr, myself.broadcast, myself.netmask);
00256 #endif
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 if ((rc = pthread_create(&control, NULL, run_controller, &myself)) < 0) {
00268 syslog(LOG_ERR, "control server: %m");
00269 exit(-1);
00270 }
00271
00272 cur = myself.protocols;
00273 while (cur != NULL) {
00274 pthread_join(cur->discover_thread, NULL);
00275 cur = cur->next;
00276 }
00277 pthread_join(stats, NULL);
00278 pthread_join(echo, NULL);
00279 pthread_join(control, NULL);
00280 return 0;
00281 }