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 <netdb.h>
00037 #include <syslog.h>
00038
00039 #include "mesh_strength.h"
00040
00041
00042 enum metric_index { min_signal = 0, };
00043
00044
00045 void strength_on_demand_discovery(protocol_t *proto, u_int32_t dest)
00046 {
00047
00048 }
00049
00050
00051 int strength_send_mesh_discovery(protocol_t *proto, int sd, int flags)
00052 {
00053 int error, i = 0;
00054 link_entry_t *entry, *dbentry;
00055 struct sockaddr_in their_addr;
00056 struct hostent *he;
00057 char link_string[MESH_LINK_STRLEN];
00058 char their_addr_string[NET_ADDR_LEN];
00059 unsigned int num_links;
00060 database_t *db;
00061
00062 if (proto == NULL) {
00063 errno = EINVAL;
00064 return -1;
00065 }
00066
00067
00068 while ((dbentry = iterate_entries(proto)) != NULL)
00069 remove_kernel_route(dbentry);
00070 empty_entries(proto);
00071
00072 if (flags == MESH_REDISCOVER) {
00073 num_links = 1;
00074 db = new_database(proto, 1);
00075 entry = new_link_entry(proto);
00076 entry->link.rediscover++;
00077 link_to_string(&entry->link, link_string);
00078 memcpy(&db->links, &entry->link, sizeof(link_t));
00079
00080 #ifdef DEBUG_DISCOVERY
00081 syslog(LOG_INFO, "(re)discover %s", proto->sensor->broadcast);
00082 #endif
00083 } else {
00084 if (proto->db_altered == 0)
00085 return 0;
00086
00087 num_links = num_entries(proto) + 1;
00088 db = new_database(proto, num_links);
00089
00090 #ifdef DEBUG_DISCOVERY
00091 syslog(LOG_INFO, "broadcast database (%d links)", num_links);
00092 #endif
00093
00094 while ((dbentry = iterate_entries(proto)) != NULL) {
00095 #ifdef DEBUG_DISCOVERY
00096 char string[MESH_LINK_STRLEN];
00097 link_to_string(&dbentry->link, string);
00098 syslog(LOG_INFO, " #%d - %d : %s", i+1, dbentry->node_id, string);
00099 #endif
00100 dbentry->link.rediscover = 0;
00101 memcpy(&db->links[i++], &dbentry->link, sizeof(link_t));
00102
00103
00104 add_kernel_route(dbentry);
00105 }
00106 entry = new_link_entry(proto);
00107 memcpy(&db->links[i], &entry->link, sizeof(link_t));
00108
00109 proto->db_altered = 0;
00110 }
00111
00112 if ((he = gethostbyname(proto->sensor->broadcast)) == NULL) {
00113 syslog(LOG_ERR, "gethostbyname(%s): %s",
00114 proto->sensor->broadcast, hstrerror(h_errno));
00115 return -1;
00116 }
00117 their_addr.sin_family = AF_INET;
00118 their_addr.sin_port = htons(MESH_DISCOVERY_PORT);
00119 their_addr.sin_addr = *((struct in_addr*)he->h_addr);
00120 memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero));
00121 strcpy(their_addr_string, ip_to_dot(their_addr.sin_addr.s_addr));
00122
00123 #ifdef DEBUG_DISCOVERY
00124 syslog(LOG_INFO, "sending %d links:", num_links);
00125 for (i = 0; i < num_links; i++) {
00126 char link_string[MESH_LINK_STRLEN];
00127 link_to_string(&db->links[i], link_string);
00128 syslog(LOG_INFO, " %s", link_string);
00129 }
00130 #endif
00131
00132 if ((error = send_routes(proto->sensor, sd, db, num_links,
00133 &their_addr)) < 0) {
00134 syslog(LOG_ERR, "rediscover send_routes %s: %m", their_addr_string);
00135 return error;
00136 }
00137
00138 #ifdef DEBUG_DISCOVERY
00139 syslog(LOG_INFO, "sent \"%s\"", link_string);
00140 #endif
00141 free(db);
00142 free(entry);
00143 return 0;
00144 }
00145
00146
00147 int strength_recv_mesh_discovery(protocol_t *proto, int sd, int num_links)
00148 {
00149 int bytes, i, signal_str = INT_MAX, noise_lvl = 0;
00150 database_t *db = malloc(database_size(num_links));
00151 link_t *links;
00152 struct sockaddr_in their_addr;
00153 struct in_addr *from;
00154 struct msghdr msg_header;
00155 struct cmsghdr *control;
00156 size_t ctl_msg_size = CMSG_SPACE(sizeof(struct in_pktinfo));
00157
00158 if (proto == NULL) {
00159 errno = EINVAL;
00160 return -1;
00161 }
00162
00163 if ((bytes = receive_routes(sd, db, num_links, &their_addr,
00164 &msg_header, ctl_msg_size)) < 0) {
00165 syslog(LOG_ERR, "receive_routes: %m");
00166 return bytes;
00167 }
00168 for (control = CMSG_FIRSTHDR(&msg_header); control != NULL;
00169 control = CMSG_NXTHDR(&msg_header, control)) {
00170 if (control->cmsg_level == SOL_IP &&
00171 control->cmsg_type == IP_PKTINFO) {
00172 struct in_pktinfo *packet_info =
00173 (struct in_pktinfo*)CMSG_DATA(control);
00174 signal_str = min(signal_str, packet_info->signal);
00175 noise_lvl = max(noise_lvl, packet_info->noise);
00176 break;
00177 }
00178 }
00179
00180 from = &their_addr.sin_addr;
00181 if (strcmp(proto->sensor->ip_addr,
00182 ip_to_dot(their_addr.sin_addr.s_addr)) == 0)
00183 return 0;
00184
00185
00186
00187 links = db->links;
00188 #ifdef DEBUG_DISCOVERY
00189 syslog(LOG_INFO, "recvd %d links: (from %s, rss: %d)", num_links,
00190 ip_to_dot(their_addr.sin_addr.s_addr), signal_str);
00191 for (i = 0; i < num_links; i++) {
00192 char string[MESH_LINK_STRLEN];
00193 link_to_string(&links[i], string);
00194 syslog(LOG_INFO, " %s", string);
00195 }
00196 #endif
00197
00198 if (links[0].rediscover != 0) {
00199 link_entry_t *dbentry;
00200 #ifdef DEBUG_DISCOVERY
00201 syslog(LOG_INFO, "rediscover initiated");
00202 #endif
00203
00204 while ((dbentry = iterate_entries(proto)) != NULL)
00205 remove_kernel_route(dbentry);
00206 empty_entries(proto);
00207 links[0].rediscover = 0;
00208 }
00209
00210 for (i = 0; i < num_links; i++) {
00211 link_entry_t *entry, *db_link;
00212
00213 entry = new_link_entry(proto);
00214 memcpy(&entry->link, &links[i], sizeof(link_t));
00215 entry->node_id = entry->link.node.s_addr;
00216 entry->link.metrics[min_signal] = INT_MAX;
00217
00218 if (strcmp(ip_to_dot(entry->link.node.s_addr),
00219 proto->sensor->ip_addr) == 0)
00220 return 0;
00221
00222 entry->link.hop_count++;
00223
00224 entry->link.metrics[min_signal] = min(entry->link.metrics[min_signal],
00225 signal_str);
00226
00227 db_link = retrieve_entry(proto, entry->node_id);
00228
00229
00230
00231 if (db_link != NULL) {
00232 #ifdef DEBUG_DISCOVERY
00233 char string[MESH_LINK_STRLEN];
00234 link_to_string(&db_link->link, string);
00235 syslog(LOG_INFO, "update link %s", string);
00236 #endif
00237
00238 if (db_link->link.metrics[min_signal] > entry->link.metrics[min_signal] ||
00239 (db_link->link.metrics[min_signal] == entry->link.metrics[min_signal] &&
00240 db_link->link.hop_count > entry->link.hop_count)) {
00241 if (memcmp(&db_link->link.next_hop, from, sizeof(from)) != 0)
00242 proto->db_altered++;
00243
00244
00245 db_link->link.metrics[min_signal] = entry->link.metrics[min_signal];
00246 db_link->link.hop_count = entry->link.hop_count;
00247 memcpy(&db_link->link.next_hop, from, sizeof(from));
00248 }
00249 free(entry);
00250 } else {
00251 #ifdef DEBUG_DISCOVERY
00252 char string[MESH_LINK_STRLEN];
00253 link_to_string(&entry->link, string);
00254 syslog(LOG_INFO, "add link %s", string);
00255 #endif
00256 add_entry(proto, entry->node_id, entry);
00257 proto->db_altered++;
00258 }
00259 }
00260
00261 free(db);
00262 return 0;
00263 }