📄 agentadv.c
字号:
/* $Id: agentadv.c,v 1.82 2001/09/29 18:29:51 jm Exp $ * ICMP Agent Advertisement/Solicitation routines * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include "config.h"#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netdb.h>#include <netinet/ip_icmp.h>#ifdef DYN_TARGET_LINUX#include <netinet/udp.h>#endif#include <arpa/inet.h>#include <assert.h>#include <string.h>#include <errno.h>#include <net/if.h>#include <asm/types.h>#include <unistd.h>#include <features.h> /* for the glibc version number */#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1#include <netpacket/packet.h>#include <net/ethernet.h> /* the L2 protocols */#include <netinet/if_ether.h>#else#ifdef DYN_TARGET_LINUX#include <linux/if_packet.h>#include <linux/if_ether.h> /* The L2 protocols */#endif#endif#include "owntypes.h"#ifdef DYN_TARGET_LINUX#include <linux/filter.h>#endif#ifndef ETHERTYPE_IP#define ETHERTYPE_IP 0x0800 /* IP */#endif#include "message.h"#include "agentadv.h"#include "dyn_ip.h"#include "util.h"#include "debug.h"#define DEBUG_FLAG 'a'/* couple of definitions from <linux/icmp.h> if they are not available * from the netinet/ip_icmp.h */#ifndef ICMP_FILTER#define ICMP_FILTER 1struct icmp_filter { __u32 data;};#endif#ifndef SOL_RAW#define SOL_RAW 255#endif#ifndef SO_BINDTODEVICE#define SO_BINDTODEVICE 25#endif/* RFC 2002, sec. 2.1: * the IP destination address of an Agent Advertisement MUST be either the * "all systems on this link" multicast address (224.0.0.1) [5] or the * "limited broadcast" address (255.255.255.255) */#define AGENT_ADV_DEST_IP "255.255.255.255"#define AGENT_SOL_DEST_IP "255.255.255.255"static struct agentadv_setup_data data;/** * set_agent_adv_data: * @_max_lifetime: * @_highest_fa_addr: * @_agent_own_addr: * @_agent_adv_opt: * @_own_agent_adv_opt: * @_adv_lifetime: * @hfa_pubkey_hash: * @hfa_pubkey_hash_len: * * */void set_agent_adv_data(__u16 _max_lifetime, struct in_addr _highest_fa_addr, struct in_addr _agent_own_addr, __u16 _agent_adv_opt, __u8 _own_agent_adv_opt, __u16 _adv_lifetime, unsigned char *hfa_pubkey_hash, int hfa_pubkey_hash_len){ data.max_lifetime = htons(_max_lifetime); data.adv_lifetime = htons(_adv_lifetime); data.highest_fa_addr = (__u32)_highest_fa_addr.s_addr; data.agent_own_addr = (__u32)_agent_own_addr.s_addr; data.agent_adv_opt = htons(_agent_adv_opt); data.own_agent_adv_opt = _own_agent_adv_opt; data.hfa_pubkey_hash = hfa_pubkey_hash; data.hfa_pubkey_hash_len = hfa_pubkey_hash_len; data.fa_nai_extension = NULL; data.challenge = NULL;}/** * set_agent_adv_nai: * @nai_ext: * * */void set_agent_adv_nai(struct fa_nai_ext *nai_ext){ data.fa_nai_extension = nai_ext;}void set_agent_adv_challenge(struct challenge_ext *challenge){ data.challenge = challenge;}#ifdef INCLUDE_IPAY/** * set_agent_adv_ipay: * @timePrice: * @bytePrice: * * */void set_agent_adv_ipay(__u32 timePrice, __u32 bytePrice){ data.timePrice = htonl(timePrice); data.bytePrice = htonl(bytePrice);}#endifstatic int user_space_filter = AGENTADV_FILTER_NONE;static int ok_buf(char *buf){ __u8 proto;#ifdef DYN_TARGET_LINUX struct iphdr *_ip = (struct iphdr *) buf; struct router_adv *_radv = (struct router_adv *) (buf + sizeof(struct iphdr));#else struct iphdr *_ip = (struct iphdr *) (buf + sizeof(struct ethhdr)); struct router_adv *_radv = (struct router_adv *) (buf + sizeof(struct ethhdr) + sizeof(struct iphdr));#endif memcpy(&proto, &_ip->protocol, 1); if (proto != IPPROTO_ICMP) return 0; if (user_space_filter == AGENTADV_FILTER_ADV && _radv->type != ICMP_ROUTERADVERT) return 0; if (user_space_filter == AGENTADV_FILTER_SOL && _radv->type != ICMP_ROUTERSOLICIT) return 0; return 1;}#ifdef DYN_TARGET_LINUX/* iphdr - 20 octets */static struct sock_filter agentadv_filter[] = { /* A <- P[9:1] - load byte - IP protocol */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), /* pc += (A == IPPROTO_ICMP) ? 0 : 3 */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_ICMP, 0, 3), /* A <- P[20:1] - load byte - ICMP type */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 20), /* pc += (A == 9) ? 0 : 1 (agentadv) */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 9, 0, 1), BPF_STMT(BPF_RET+BPF_K, (__u32)-1), /* accept the packet */ BPF_STMT(BPF_RET+BPF_K, 0) /* filter packet */};static struct sock_fprog agentadv_fprog = { sizeof(agentadv_filter) / sizeof(struct sock_filter), agentadv_filter};/* iphdr - 20 octets */static struct sock_filter agentsol_filter[] = { /* A <- P[9:1] - load byte - IP protocol */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), /* pc += (A == IPPROTO_ICMP) ? 0 : 3 */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_ICMP, 0, 3), /* A <- P[20:1] - load byte - ICMP type */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 20), /* pc += (A == 10) ? 0 : 1 (agentsol) */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 10, 0, 1), BPF_STMT(BPF_RET+BPF_K, (__u32)-1), /* accept the packet */ BPF_STMT(BPF_RET+BPF_K, 0) /* filter packet */};static struct sock_fprog agentsol_fprog = { sizeof(agentsol_filter) / sizeof(struct sock_filter), agentsol_filter};static struct sock_filter udp434_filter[] = { /* A <- P[9:1] - load byte - IP protocol */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), /* pc += (A == IPPROTO_ICMP) ? 0 : 3 */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_UDP, 0, 3), /* A <- P[20:1] - load half word - dest port */ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 22), /* pc += (A == 434) ? 0 : 1 (agentadv) */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 434, 0, 1), BPF_STMT(BPF_RET+BPF_K, (__u32)-1), /* accept the packet */ BPF_STMT(BPF_RET+BPF_K, 0) /* filter packet */};static struct sock_fprog udp434_fprog = { sizeof(udp434_filter) / sizeof(struct sock_filter), udp434_filter};#endif/** * open_agent_icmp_adv_socket: * @dev: * * * * Returns: */int open_agent_icmp_adv_socket(char *dev, int filter){#ifdef DYN_TARGET_LINUX int s, i; struct sockaddr_ll sa; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memset(&sa, 0, sizeof(sa)); s = socket(PF_PACKET, SOCK_DGRAM, htons(ETHERTYPE_IP)); if (s < 0) { if (errno == EPERM) DEBUG(DEBUG_FLAG, "Must be run as root\n"); DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket - socket: %s\n", strerror(errno)); return -1; } if (filter == AGENTADV_FILTER_ADV && setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &agentadv_fprog, sizeof(agentadv_fprog)) < 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket - setsockopt: " "%s\n", strerror(errno)); user_space_filter = filter; } else if (filter == AGENTADV_FILTER_SOL && setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &agentsol_fprog, sizeof(agentsol_fprog)) < 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket - setsockopt: " "%s\n", strerror(errno)); user_space_filter = filter; } else if (filter == UDP_FILTER_PORT434 && setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &udp434_fprog, sizeof(udp434_fprog)) < 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket - setsockopt: " "%s\n", strerror(errno)); } i = strlen(dev); if (i >= sizeof(ifr.ifr_name)) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket: too long " "interface parameter\n"); return -1; } memcpy(ifr.ifr_name, dev, i + 1); if (ioctl(s, SIOCGIFINDEX, &ifr) != 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket(%s): ioctl: " "%s\n", dev, strerror(errno)); close(s); return -1; } sa.sll_family = AF_PACKET; sa.sll_ifindex = ifr.ifr_ifindex; if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_adv_socket - bind: %s\n", strerror(errno)); return -1; } return s;#endif#ifdef DYN_TARGET_WINDOWS struct sockaddr_in addr; int s; /* FIX: should use something to get the real ICMP packets with ethernet * header.. */ DEBUG(DEBUG_FLAG, "ICMP adv socket as a UDP kludge\n"); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_socket - socket: %s\n", strerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(4344); if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { DEBUG(DEBUG_FLAG, "bind: %s\n", strerror(errno)); close(s); return -1; } return s;#endif}/** * open_agent_icmp_socket: * @dev: if != NULL then the socket will be bound to a local address * used for the device in order to send the broadcast messages to the * specified device * @filter: * * Returns: */int open_agent_icmp_socket(char *dev, __u32 filter){ int s;#ifdef DYN_TARGET_LINUX struct protoent *proto; struct icmp_filter ifilter; struct ip_mreq imr; if (!(proto = getprotobyname("icmp"))) { DEBUG(DEBUG_FLAG, "getprotobyname - unknown protocol icmp - %s\n", strerror(errno)); return -1; } if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { if (errno == EPERM) DEBUG(DEBUG_FLAG, "Must be run as root\n"); DEBUG(DEBUG_FLAG, "open_agent_icmp_socket - socket: %s\n", strerror(errno)); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -