📄 link_layer.c
字号:
/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2004, Andreas T鴑nesen(andreto@olsr.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of olsr.org, olsrd nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: link_layer.c,v 1.14 2007/08/19 23:00:15 bernd67 Exp $ */#if 0 /* DEPRECATED - KEPT FOR REFERENCE *//* Ugly fix to make this compile on wireless extentions < 16 */#define _LINUX_ETHTOOL_H#include "../link_layer.h"#include "../olsr_protocol.h"#include "../scheduler.h"#include "../interfaces.h"#include <linux/wireless.h>#include <linux/icmp.h>#include <errno.h>#include <string.h>#include <sys/ioctl.h>#include <net/if_arp.h>#include <unistd.h>#include <stdlib.h>#include "olsr_protocol.h"voidinit_link_layer_notification(void);voidpoll_link_layer(void *);intadd_spy_node(union olsr_ip_addr *, char *);#define MAXIPLEN 60#define MAXICMPLEN 76float poll_int = 0.2;intiw_get_range_info(char *, struct iw_range *);intclear_spy_list(char *);intconvert_ip_to_mac(union olsr_ip_addr *, struct sockaddr *, char *);voidsend_ping(union olsr_ip_addr *);voidinit_link_layer_notification(){ struct interface *ifd; OLSR_PRINTF(1, "Initializing link-layer notification...\n"); for (ifd = ifnet; ifd ; ifd = ifd->int_next) { if(ifd->is_wireless) clear_spy_list(ifd->int_name); } olsr_register_scheduler_event(&poll_link_layer, NULL, poll_int, 0, NULL); return;}intclear_spy_list(char *ifname){ struct iwreq wrq; /* Time to do send addresses to the driver */ wrq.u.data.pointer = NULL;//(caddr_t) hw_address; wrq.u.data.length = 0; wrq.u.data.flags = 0; /* Set device name */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(olsr_cnf->ioctl_s, SIOCSIWSPY, &wrq) < 0) { OLSR_PRINTF(1, "Could not clear spylist %s\n", strerror(errno)); return -1; } return 1;}intadd_spy_node(union olsr_ip_addr *addr, char *interface){ struct sockaddr new_node; struct iwreq wrq; int nbr; /* Number of valid addresses */ struct sockaddr hw_address[IW_MAX_SPY]; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; OLSR_PRINTF(1, "Adding spynode!\n\n"); /* get all addresses already in the driver */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; strncpy(wrq.ifr_name, interface, IFNAMSIZ); if(ioctl(olsr_cnf->ioctl_s, SIOCGIWSPY, &wrq) < 0) { OLSR_PRINTF(1, "Could not get old spylist %s\n", strerror(errno)); return 0; } /* Copy old addresses */ nbr = wrq.u.data.length; memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); OLSR_PRINTF(1, "Old addresses: %d\n\n", nbr); /* Check upper limit */ if(nbr >= IW_MAX_SPY) return 0; /* Add new address if MAC exists in ARP cache */ if(convert_ip_to_mac(addr, &new_node, interface) > 0) { memcpy(&hw_address[nbr], &new_node, sizeof(struct sockaddr)); nbr++; } else return 0; /* Add all addresses */ wrq.u.data.pointer = (caddr_t) hw_address; wrq.u.data.length = nbr; wrq.u.data.flags = 0; /* Set device name */ strncpy(wrq.ifr_name, interface, IFNAMSIZ); if(ioctl(olsr_cnf->ioctl_s, SIOCSIWSPY, &wrq) < 0) { OLSR_PRINTF(1, "Could not clear spylist %s\n", strerror(errno)); return 0; } return 1;}intconvert_ip_to_mac(union olsr_ip_addr *ip, struct sockaddr *mac, char *interface){ struct arpreq arp_query; struct sockaddr_in tmp_sockaddr; memset(&arp_query, 0, sizeof(struct arpreq)); OLSR_PRINTF(1, "\nARP conversion for %s interface %s\n", olsr_ip_to_string(ip), interface); tmp_sockaddr.sin_family = AF_INET; tmp_sockaddr.sin_port = 0; memcpy(&tmp_sockaddr.sin_addr, ip, olsr_cnf->ipsize); /* Translate IP addresses to MAC addresses */ memcpy(&arp_query.arp_pa, &tmp_sockaddr, sizeof(struct sockaddr_in)); arp_query.arp_ha.sa_family = 0; arp_query.arp_flags = 0; strncpy(arp_query.arp_dev, interface, IFNAMSIZ); if((ioctl(olsr_cnf->ioctl_s, SIOCGARP, &arp_query) < 0) || !(arp_query.arp_flags & ATF_COM)) /* ATF_COM - hw addr valid */ { OLSR_PRINTF(1, "Arp failed: (%s) - trying lookup\n", strerror(errno)); /* No address - create a thread that sends a PING */ send_ping(ip); return -1; } OLSR_PRINTF(1, "Arp success!\n"); memcpy(mac, &arp_query.arp_ha, sizeof(struct sockaddr)); return 1;}/** *A thread that sends a ICMP echo "ping" packet *to a given destination to force the ARP cache *to be updated... kind of a kludge.... * *@param _ip the IP address to ping *//* ONLY IPv4 FOR NOW!!! */voidsend_ping(union olsr_ip_addr *ip){ int ping_s; struct sockaddr dst; struct sockaddr_in *dst_in; char *packet; struct icmphdr *icp; dst_in = (struct sockaddr_in *) &dst; dst_in->sin_family = AF_INET; memcpy(&dst_in->sin_addr, ip, olsr_cnf->ipsize); OLSR_PRINTF(1, "pinging %s\n\n", olsr_ip_to_string(ip)); if ((ping_s = socket(AF_INET, SOCK_RAW, PF_INET)) < 0) { OLSR_PRINTF(1, "Could not create RAW socket for ping!\n%s\n", strerror(errno)); return; } /* Create packet */ packet = malloc(MAXIPLEN + MAXICMPLEN); icp = (struct icmphdr *)packet; icp->type = ICMP_ECHO; icp->code = 0; icp->checksum = 0; icp->un.echo.sequence = 1; icp->un.echo.id = getpid() & 0xFFFF; if((sendto(ping_s, packet, MAXIPLEN + MAXICMPLEN + 8, 0, &dst, sizeof(struct sockaddr))) != MAXIPLEN + MAXICMPLEN + 8) { OLSR_PRINTF(1, "Error PING: %s\n", strerror(errno)); } /* Nevermind the pong ;-) */ OLSR_PRINTF(1, "Ping complete...\n"); close(ping_s); free(packet); return;}voidpoll_link_layer(void *foo){ struct iwreq wrq; char buffer[(sizeof(struct iw_quality) + sizeof(struct sockaddr)) * IW_MAX_SPY]; struct sockaddr *hwa; struct iw_quality *qual; int n; struct iw_range range; int i, j; int has_range = 0; struct interface *iflist; //OLSR_PRINTF(1, "Polling link-layer notification...\n"); for(iflist = ifnet; iflist != NULL; iflist = iflist->int_next) { if(!iflist->is_wireless) continue; /* Collect stats */ wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = IW_MAX_SPY; wrq.u.data.flags = 0; /* Set device name */ strncpy(wrq.ifr_name, iflist->int_name, IFNAMSIZ); /* Do the request */ if(ioctl(olsr_cnf->ioctl_s, SIOCGIWSPY, &wrq) < 0) { OLSR_PRINTF(1, "%-8.16s Interface doesn't support wireless statistic collection\n\n", iflist->int_name); return; } /* Get range info if we can */ if(iw_get_range_info(iflist->int_name, &(range)) >= 0) has_range = 1; /* Number of addresses */ n = wrq.u.data.length; /* The two lists */ hwa = (struct sockaddr *) buffer; qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); for(i = 0; i < n; i++) { if(!(qual->updated & 0x7)) continue; /* Print stats for each address */ OLSR_PRINTF(1, "MAC"); for(j = 0; j < 6; j++) { OLSR_PRINTF(1, ":%02x", (hwa[i].sa_data[j] % 0xffffff00)); } if(!has_range) OLSR_PRINTF(1, " : Quality:%d Signal level:%d dBm Noise level:%d dBm", qual[i].qual, qual[i].level - 0x100, qual[i].noise - 0x100); else OLSR_PRINTF(1, " : Quality:%d/%d Signal level:%d dBm Noise level:%d dBm", qual[i].qual, range.max_qual.qual, qual[i].level - 0x100, qual[i].noise - 0x100); OLSR_PRINTF(1, "\n"); } } //OLSR_PRINTF(1, "\n"); return;}/* * Get the range information out of the driver */intiw_get_range_info(char *ifname, struct iw_range *range){ struct iwreq wrq; char buffer[sizeof(struct iw_range) * 2]; /* Large enough */ union iw_range_raw *range_raw; /* Cleanup */ bzero(buffer, sizeof(buffer)); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = sizeof(buffer); wrq.u.data.flags = 0; /* Set device name */ strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if(ioctl(olsr_cnf->ioctl_s, SIOCGIWRANGE, &wrq) < 0) { OLSR_PRINTF(1, "NO RANGE\n"); return -1; } /* Point to the buffer */ range_raw = (union iw_range_raw *) buffer; memcpy((char *) range, buffer, sizeof(struct iw_range)); return 1;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -