00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <time.h>
00041 #include <unistd.h>
00042 #include <malloc.h>
00043 #include <net/if_arp.h>
00044 #include <netinet/in.h>
00045 #include <netinet/if_ether.h>
00046 #include <linux/rtnetlink.h>
00047 #include <arpa/inet.h>
00048 #include <sys/ioctl.h>
00049 #include <sys/socket.h>
00050 #include <errno.h>
00051
00052 #include "olsr.h"
00053 #include "defs.h"
00054 #include "olsr_types.h"
00055 #include "olsr_logging.h"
00056 #include "olsr_timer.h"
00057 #include "olsr_socket.h"
00058 #include "plugin_util.h"
00059 #include "olsr_ip_prefix_list.h"
00060 #include "net_olsr.h"
00061
00062 #define PLUGIN_DESCR "Arproaming olsrd plugin v0.1"
00063 #define PLUGIN_AUTHOR "amadeus"
00064
00065 static int arproaming_init(void);
00066 static int arproaming_exit(void);
00067
00068 static void arproaming_schedule_event(void *);
00069 static void arproaming_list_add(unsigned int timeout, const union olsr_ip_addr *ip, const struct olsr_mac48_addr *mac);
00070 static void arproaming_list_remove(const struct olsr_mac48_addr *mac);
00071 static void arproaming_client_add(void);
00072 static void arproaming_client_remove(const union olsr_ip_addr *ip);
00073 static int arproaming_client_probe(const union olsr_ip_addr *ip);
00074 static void arproaming_client_update(void);
00075 static void arproaming_systemconf(int arproaming_socketfd_system);
00076
00077 #if 0
00078 static void arproaming_list_update(const union olsr_ip_addr *ip, unsigned int timeout);
00079 #endif
00080
00081 struct arproaming_nodes {
00082 struct list_entity node;
00083 unsigned int timeout;
00084 union olsr_ip_addr ip;
00085 struct olsr_mac48_addr mac;
00086 };
00087
00088 static struct olsr_timer_info *timer_info;
00089 static struct olsr_timer_entry *event_timer;
00090
00091 static char arproaming_parameter_interface[25];
00092 static int arproaming_parameter_timeout;
00093
00094 static int arproaming_socketfd_netlink = -1;
00095 static int arproaming_socketfd_arp = -1;
00096 static union olsr_ip_addr arproaming_srcip;
00097
00098 static struct olsr_mac48_addr arproaming_srcmac;
00099
00100 static struct list_entity arproaming_nodes;
00101
00102 static const struct olsrd_plugin_parameters plugin_parameters[] = {
00103 { .name = "Interface", .set_plugin_parameter = &set_plugin_string, .data = &arproaming_parameter_interface, .addon.ui = sizeof(arproaming_srcmac)},
00104 { .name = "Timeout", .set_plugin_parameter = &set_plugin_int, .data = &arproaming_parameter_timeout }
00105 };
00106
00107 OLSR_PLUGIN6(plugin_parameters) {
00108 .descr = PLUGIN_DESCR,
00109 .author = PLUGIN_AUTHOR,
00110 .init = arproaming_init,
00111 .exit = arproaming_exit,
00112 .deactivate = false
00113 };
00114
00115 static void
00116 arproaming_list_add(unsigned int timeout, const union olsr_ip_addr *ip, const struct olsr_mac48_addr *mac)
00117 {
00118 struct arproaming_nodes *new;
00119
00120 new = malloc(sizeof(*new));
00121
00122 new->timeout = timeout;
00123 memcpy(&new->ip, ip, sizeof(*ip));
00124 memcpy(&new->mac, mac, sizeof(*mac));
00125
00126 list_add_tail(&arproaming_nodes, &new->node);
00127 }
00128
00129 static void
00130 arproaming_list_remove(const struct olsr_mac48_addr *mac)
00131 {
00132 struct arproaming_nodes *element, *iterator;
00133
00134 list_for_each_element_safe(&arproaming_nodes, element, node, iterator) {
00135 if (memcmp(&element->mac, mac, sizeof(*mac)) == 0) {
00136 list_remove(&element->node);
00137 free(element);
00138 }
00139 }
00140 }
00141
00142 #if 0
00143 static void
00144 arproaming_list_update(const union olsr_ip_addr *ip, unsigned int timeout)
00145 {
00146 struct arproaming_nodes *element;
00147
00148 list_for_each_element(&arproaming_nodes, element, node) {
00149 if (olsr_ipcmp(&element->ip, ip) == 0) {
00150 element->timeout = timeout;
00151 break;
00152 }
00153 }
00154 }
00155 #endif
00156
00157 static void
00158 arproaming_client_add(void)
00159 {
00160 int status, rtattrlen, len;
00161 char buf[10240];
00162 struct olsr_mac48_addr mac;
00163
00164 struct {
00165 struct nlmsghdr n;
00166 struct ndmsg r;
00167 } req;
00168 struct rtattr *rta, *rtatp;
00169 struct nlmsghdr *nlmsghdr;
00170 struct ndmsg *ndmsg;
00171 struct ifaddrmsg *ifa;
00172 struct in_addr *in;
00173 union olsr_ip_addr host_net;
00174
00175 memset(&req, 0, sizeof(req));
00176 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
00177 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
00178 req.n.nlmsg_type = RTM_NEWNEIGH | RTM_GETNEIGH;
00179 req.r.ndm_family = AF_INET;
00180
00181 rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
00182 rta->rta_len = RTA_LENGTH(4);
00183
00184 send(arproaming_socketfd_netlink, &req, req.n.nlmsg_len, 0);
00185 status = recv(arproaming_socketfd_netlink, buf, sizeof(buf), 0);
00186
00187 for(nlmsghdr = (struct nlmsghdr *)buf; (unsigned int) status > sizeof(*nlmsghdr);) {
00188 len = nlmsghdr->nlmsg_len;
00189 ndmsg = (struct ndmsg *)NLMSG_DATA(nlmsghdr);
00190 rtatp = (struct rtattr *)IFA_RTA(ndmsg);
00191 rtattrlen = IFA_PAYLOAD(nlmsghdr);
00192 rtatp = RTA_NEXT(rtatp, rtattrlen);
00193 ifa = (struct ifaddrmsg *)NLMSG_DATA(nlmsghdr);
00194
00195
00196 if (rtatp->rta_type == IFA_ADDRESS && ndmsg->ndm_state & NUD_REACHABLE) {
00197 in = (struct in_addr *)RTA_DATA(rtatp);
00198 host_net.v4 = *in;
00199
00200 if (ip_prefix_list_find(&olsr_cnf->hna_entries, &host_net, 32, 4) == NULL && if_nametoindex(arproaming_parameter_interface) == ifa->ifa_index) {
00201 #if !defined REMOVE_LOG_DEBUG
00202 struct ipaddr_str ipbuf;
00203 #endif
00204 memcpy(&mac, RTA_DATA(rtatp), sizeof(mac));
00205
00206 ip_prefix_list_add(&olsr_cnf->hna_entries, &host_net, 32);
00207 arproaming_list_add(time(NULL) + arproaming_parameter_timeout, &host_net, &mac);
00208
00209 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Adding host %s\n", olsr_ip_to_string(&ipbuf, &host_net));
00210 }
00211 }
00212
00213 status -= NLMSG_ALIGN(len);
00214 nlmsghdr = (struct nlmsghdr*)((char*)nlmsghdr + NLMSG_ALIGN(len));
00215 }
00216 }
00217
00218 static void
00219 arproaming_client_remove(const union olsr_ip_addr *ip)
00220 {
00221 int socketfd;
00222 struct arpreq req;
00223 struct sockaddr_in *sin;
00224
00225 socketfd = socket(AF_INET, SOCK_DGRAM, 0);
00226
00227 memset(&req, 0, sizeof(struct arpreq));
00228 sin = (struct sockaddr_in *) &req.arp_pa;
00229 sin->sin_family = AF_INET;
00230 sin->sin_addr = ip->v4;
00231 strcpy(req.arp_dev, arproaming_parameter_interface);
00232
00233 ioctl(socketfd, SIOCDARP, (caddr_t)&req);
00234 close(socketfd);
00235 }
00236
00237 static int
00238 arproaming_client_probe(const union olsr_ip_addr *ip)
00239 {
00240 int ret = 0;
00241 int timeout = 1;
00242 struct arpMsg {
00243 struct ethhdr ethhdr;
00244 u_short htype;
00245 u_short ptype;
00246 u_char hlen;
00247 u_char plen;
00248 u_short operation;
00249 u_char sHaddr[6];
00250 u_char sInaddr[4];
00251 u_char tHaddr[6];
00252 u_char tInaddr[4];
00253 };
00254 struct sockaddr addr;
00255 struct arpMsg arp;
00256 fd_set fdset;
00257 struct timeval tm;
00258 time_t prevTime;
00259
00260 memset(&arp, 0, sizeof(arp));
00261 memcpy(arp.ethhdr.h_dest, "\xFF\xFF\xFF\xFF\xFF\xFF", 6);
00262 memcpy(arp.ethhdr.h_source, &arproaming_srcmac, sizeof(arproaming_srcmac));
00263 arp.ethhdr.h_proto = htons(ETH_P_ARP);
00264 arp.htype = htons(ARPHRD_ETHER);
00265 arp.ptype = htons(ETH_P_IP);
00266 arp.hlen = 6;
00267 arp.plen = 4;
00268 arp.operation = htons(ARPOP_REQUEST);
00269 memcpy(arp.sInaddr, &arproaming_srcip, sizeof(arp.sInaddr));
00270 memcpy(arp.sHaddr, &arproaming_srcmac, sizeof(arproaming_srcmac));
00271 memcpy(arp.tInaddr, ip, sizeof(arp.tInaddr));
00272
00273 memset(&addr, 0, sizeof(addr));
00274 strcpy(addr.sa_data, arproaming_parameter_interface);
00275 sendto(arproaming_socketfd_arp, &arp, sizeof(arp), 0, &addr, sizeof(addr));
00276
00277 tm.tv_usec = 0;
00278 time(&prevTime);
00279 while (timeout > 0) {
00280 FD_ZERO(&fdset);
00281 FD_SET(arproaming_socketfd_arp, &fdset);
00282 tm.tv_sec = timeout;
00283 select(arproaming_socketfd_arp + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm);
00284
00285 if (FD_ISSET(arproaming_socketfd_arp, &fdset)) {
00286 recv(arproaming_socketfd_arp, &arp, sizeof(arp), 0);
00287 if (arp.operation == htons(ARPOP_REPLY)
00288 && memcmp(arp.tHaddr, &arproaming_srcmac, 6) == 0
00289 && memcmp(arp.sInaddr, &ip, sizeof(arp.sInaddr)) == 0) {
00290 ret = 1;
00291 break;
00292 }
00293 }
00294
00295 timeout -= time(NULL) - prevTime;
00296 time(&prevTime);
00297 }
00298
00299 return ret;
00300 }
00301
00302 static void
00303 arproaming_client_update(void)
00304 {
00305 struct arproaming_nodes *element, *iterator;
00306 #if !defined REMOVE_LOG_DEBUG
00307 struct ipaddr_str buf;
00308 #endif
00309
00310 list_for_each_element_safe(&arproaming_nodes, element, node, iterator) {
00311 if (element->timeout > 0 && element->timeout <= (unsigned int)time(NULL)) {
00312 if (arproaming_client_probe(&element->ip) == 0) {
00313 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Removing host %s\n", olsr_ip_to_string(&buf, &element->ip));
00314 ip_prefix_list_remove(&olsr_cnf->hna_entries, &element->ip, 32, 4);
00315 arproaming_client_remove(&element->ip);
00316 arproaming_list_remove(&element->mac);
00317 break;
00318 }
00319 else {
00320 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Renewing host %s\n", olsr_ip_to_string(&buf, &element->ip));
00321 element->timeout = time(NULL) + arproaming_parameter_timeout;
00322 }
00323 }
00324 }
00325 }
00326
00327 static void
00328 arproaming_systemconf(int arproaming_socketfd_system)
00329 {
00330 int i, optval = 1;
00331 char buf[1024];
00332 struct ifreq ifa, *IFR;
00333 struct sockaddr_in *in;
00334 struct ifconf ifc;
00335
00336 strcpy(ifa.ifr_name, arproaming_parameter_interface);
00337 ioctl(arproaming_socketfd_system, SIOCGIFADDR, &ifa);
00338 in = (struct sockaddr_in*)&ifa.ifr_addr;
00339
00340 memset(&arproaming_srcip, 0, sizeof(arproaming_srcip));
00341 memcpy(&arproaming_srcip, &in->sin_addr, sizeof(in->sin_addr));
00342
00343 ifc.ifc_len = sizeof(buf);
00344 ifc.ifc_buf = buf;
00345 ioctl(arproaming_socketfd_system, SIOCGIFCONF, &ifc);
00346
00347 IFR = ifc.ifc_req;
00348 for (i = ifc.ifc_len / sizeof(struct ifreq); i-- >= 0; IFR++) {
00349 strcpy(ifa.ifr_name, IFR->ifr_name);
00350 if (ioctl(arproaming_socketfd_system, SIOCGIFFLAGS, &ifa) == 0) {
00351 if (! (ifa.ifr_flags & IFF_LOOPBACK)) {
00352 if (ioctl(arproaming_socketfd_system, SIOCGIFHWADDR, &ifa) == 0) {
00353 break;
00354 }
00355 }
00356 }
00357 }
00358 memcpy(ifa.ifr_hwaddr.sa_data, &arproaming_srcmac, sizeof(arproaming_srcmac));
00359 close(arproaming_socketfd_system);
00360
00361 setsockopt(arproaming_socketfd_arp, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
00362 }
00363
00364 static void
00365 arproaming_schedule_event(void *foo __attribute__ ((unused)))
00366 {
00367 arproaming_client_add();
00368 arproaming_client_update();
00369 }
00370
00371 static int
00372 arproaming_init(void)
00373 {
00374 int arproaming_socketfd_system = -1;
00375 struct olsr_mac48_addr mac;
00376
00377 list_init_head(&arproaming_nodes);
00378
00379 memset(&mac, 0, sizeof(mac));
00380 arproaming_list_add(0, &all_zero, &mac);
00381
00382 arproaming_socketfd_netlink = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
00383 if (arproaming_socketfd_netlink < 0) {
00384 OLSR_WARN(LOG_PLUGINS, "Cannot open netlink socket for arproaming plugin: %s (%d)",
00385 strerror(errno), errno);
00386 return 1;
00387 }
00388
00389 arproaming_socketfd_arp = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
00390 if (arproaming_socketfd_arp < 0) {
00391 OLSR_WARN(LOG_PLUGINS, "Cannot open raw socket for arproaming plugin: %s (%d)",
00392 strerror(errno), errno);
00393 close (arproaming_socketfd_netlink);
00394 return 1;
00395 }
00396
00397 arproaming_socketfd_system = socket(AF_INET, SOCK_DGRAM, 0);
00398 if (arproaming_socketfd_system < 0) {
00399 OLSR_WARN(LOG_PLUGINS, "Cannot open configuration socket for arproaming plugin: %s (%d)",
00400 strerror(errno), errno);
00401 close (arproaming_socketfd_netlink);
00402 close (arproaming_socketfd_arp);
00403 return 1;
00404 }
00405
00406 arproaming_systemconf(arproaming_socketfd_system);
00407
00408 timer_info = olsr_timer_add("arproaming", &arproaming_schedule_event, true);
00409 event_timer = olsr_timer_start(MSEC_PER_SEC/3, 0, NULL, timer_info);
00410
00411 close(arproaming_socketfd_system);
00412 return 0;
00413 }
00414
00415 static int
00416 arproaming_exit(void)
00417 {
00418 olsr_timer_stop(event_timer);
00419
00420 if (arproaming_socketfd_netlink >= 0) {
00421 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Closing netlink socket.\n");
00422 close(arproaming_socketfd_netlink);
00423 }
00424
00425 if (arproaming_socketfd_arp >= 0) {
00426 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Closing arp socket.\n");
00427 close(arproaming_socketfd_arp);
00428 }
00429
00430 OLSR_DEBUG(LOG_PLUGINS, "[ARPROAMING] Exiting.\n");
00431
00432 return 0;
00433 }