#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define __USE_GNU /* luna_g3 need this macro to define struct in6_pktinfo in linux/in.h */
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
//#include <net/if.h> /* this may cause redefined error with <linux/if.h> in some tool chain. */
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <config/autoconf.h>
#include <linux/autoconf.h>
#include <errno.h>
#include <linux/if.h>
#include <rtk/utility.h>
#include <rtk/mib.h>
#define MAX_RDNSS_NUM 3
#define MAX_DNS_STRING_LEN 128
#if 0 /* Avoid to redefined the struct in6_pktinfo in linux/ipv6.h */
#ifndef __USE_GNU /* from linux/in.h*/
struct in6_pktinfo
{
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
#endif
#endif
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
#endif
#ifndef ND_OPT_RDNSS
#define ND_OPT_RDNSS 25
#endif
#ifndef ND_OPT_MTU
#define ND_OPT_MTU 5
#endif
#ifndef ND_OPT_DNSSL
#define ND_OPT_DNSSL 31
#endif
#define DEBUG_INFO(fmt,arg...) do{if(debug_flag==0)break;fprintf(stderr,"[ramonitor]%s@%d>>> ",__func__,__LINE__);fprintf(stderr,fmt,##arg);}while(0)
#define DEBUG_ERROR(fmt,arg...) do{fprintf(stderr,"ERROR! [ramonitor]%s@%d>>> ",__func__,__LINE__);fprintf(stderr,fmt,##arg);}while(0)
#define RA_INFO_FILE "/var/rainfo_"
#define SYSTEMD_PIDFILE "/var/run/systemd.pid"
#define PID_FILE "/var/run/ramonitor.pid"
/* #define RA_INFO_FILE "/var/dhcp6_info.conf" */
#define MAX_WAN_DEV_NUM 8 /* Now we only support 8 WAN. */
#define EPOLL_MAXEVENTS 1
/* This struct can be used for other ND Option */
struct nd_opt_rdnss
{
uint8_t nd_opt_rdnss_type;
uint8_t nd_opt_rdnss_len;
uint16_t nd_opt_rdnss_resserved1;
uint32_t nd_opt_rdnss_lifetime;
/* followed by one or more IPv6 addresses */
};
struct nd_opt_mtu_t
{
uint8_t nd_opt_type;
uint8_t nd_opt_len;
uint16_t nd_opt_resserved1;
uint32_t nd_opt_mtu_data;
/* followed by one or more IPv6 addresses */
};
struct ra_conf{
uint8_t valid;
uint32_t ifindex;
uint8_t if_name[IFNAMSIZ];
struct in6_addr srcip; /* src ip of RA packet */
/* Maybe in the future, we need to support multi_prefix. We can use prefix[MAX_PREFIX_NUM] or struct in6_addr prefix2 ... */
struct in6_addr prefix; /* prefix of icmpv6 option(Prefix information) */
uint8_t prefix_len;
uint8_t prefix_onlink;
uint32_t prefix_validtime;
uint32_t prefix_preferredtime;
uint8_t M; /* M flag of RA packet */
uint8_t O; /* O flag of RA packet */
uint16_t lifetime;
uint8_t rdnss[MAX_RDNSS_NUM][INET6_ADDRSTRLEN]; /* Now we only support 3 RDNSS. */
uint16_t rdnss_lifetime[MAX_RDNSS_NUM]; /* Now we only support 3 RDNSS. */
uint32_t mtu;
uint8_t dnssl[MAX_DNS_STRING_LEN];
uint16_t dnssl_lifetime;
};
struct link_status_entry{
char ifname[IFNAMSIZ];
struct ifinfomsg ifi;
struct link_status_entry *next;
};
struct link_status_entry *link_head=NULL;
struct ra_conf wan_ra_conf[MAX_WAN_DEV_NUM];
struct epoll_event* events_list = NULL;
int efd = 0;
int sock_nl = -1; /* netlink sock to receive intf create/delete/up/down events */
int sock_icmpv6 = 0;
int debug_flag = 0;
static void log_pid(void);
static int init_netlink_socket(void);
static int init_socket(void);
static int init_epoll(void);
int parse_rdnss(const struct nd_opt_hdr *opt_hdr, struct ra_conf *conf, const char *ifname);
int parse_dnssl(const struct nd_opt_hdr *opt_hdr, struct ra_conf *conf, const char *ifname);
int parse_mtu(const struct nd_opt_hdr *opt_hdr, struct ra_conf *conf, const char *ifname);
static void init_ra_conf(void);
static int indextoname(int fd, int index, char *name);
static int get_wan_ifindex(struct msghdr * msgptr, struct ra_conf * conf);
static int parse_ra(char* buf, int datalen, struct ra_conf * conf);
static void dump_ra_conf(struct ra_conf * conf);
static int check_conf(struct ra_conf * conf);
static int compare_rdnss(struct ra_conf *conf1, struct ra_conf *conf2);
static void save_ra_conf(struct ra_conf * conf);
static void delete_ra_conf(const char *intf);
static int nl_handler(int sock);
static void process_icmpv6_packet(char* buf, int datalen, char* in_dev, const void * srcIp6, struct msghdr * msgptr);
static void do_epoll(void);
void exit_clean(void);
static void sig_handler(int signum);
static void log_pid(void)
{
FILE *f;
pid_t pid;
pid = getpid();
if((f = fopen(PID_FILE, "w")) == NULL)
return;
fprintf(f, "%d\n", pid);
fclose(f);
}
void deleteLinkEntry(struct link_status_entry **head, const char *ifname){
struct link_status_entry *curr=NULL, *parent=NULL;
unsigned char len=0;
if(!ifname){
DEBUG_ERROR("null parameters\n");
return;
}
/* search entry */
curr = *head;
while(curr){
len = (strlen(curr->ifname)>strlen(ifname))?strlen(curr->ifname):strlen(ifname);
if(!strncmp(curr->ifname, ifname, len)){
if(parent){
parent->next = curr->next;
free(curr);
}else{
/* first entry */
*head = curr->next;
free(curr);
}
DEBUG_INFO("free %s\n", ifname);
break;
}
parent = curr;
curr = curr->next;
}
return;
}
struct link_status_entry *updateLinkEntry(struct link_status_entry **head, const char *ifname, struct ifinfomsg *ifi){
struct link_status_entry *curr=NULL;
unsigned int currFlags=0;
unsigned char len=0;
if(!ifname | !ifi){
DEBUG_ERROR("null parameters\n");
return NULL;
}
/* netlink event should not realtime status, it has timing delay,
* So, update flags to reduce some unnecessary processing */
if (getInFlags( ifname, &currFlags) == 0){
DEBUG_ERROR("get %s current interface flags fail\n", ifname);
return NULL;
}
if(currFlags != ifi->ifi_flags){
DEBUG_INFO("[%s] update flags from 0x%x to 0x%x\n", __FUNCTION__, ifi->ifi_flags, currFlags);
ifi->ifi_flags = currFlags;
}
/* search entry */
curr = *head;
while(curr){
len = (strlen(curr->ifname)>strlen(ifname))?strlen(curr->ifname):strlen(ifname);
if(!strncmp(curr->ifname, ifname, len)){
/* Extry exist, copy and update change mask */
ifi->ifi_change = curr->ifi.ifi_flags ^ ifi->ifi_flags;
memcpy(&curr->ifi, ifi, sizeof(curr->ifi));
return curr;
}
curr = curr->next;
}
/* entry not exist, new it */
curr = (struct link_status_entry *)calloc(1, sizeof(struct link_status_entry));
if(!curr){
DEBUG_ERROR("allocate memory fail\n");
return NULL;
}
strncpy(curr->ifname, ifname, sizeof(curr->ifname));
// exclusive or with 0x0 to get what flag it set
ifi->ifi_change = ifi->ifi_flags ^ 0x0;
memcpy(&curr->ifi, ifi, sizeof(curr->ifi));
curr->next = NULL;
if(!*head){
*head = curr;
}else{
curr->next = *head;
*head = curr;
}
return curr;
}
static int init_netlink_socket(void)
{
struct sockaddr_nl sa;
if ((sock_nl = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
{
DEBUG_ERROR("%d:%s", errno, strerror(errno));
return -1;
}
memset (&sa,0,sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_pad = 0;
sa.nl_pid = getpid();
/* monitor network interface create/delete/up/down events */
sa.nl_groups = RTMGRP_LINK;
if (bind(sock_nl, (struct sockaddr *)&sa, sizeof(sa)) == -1)
{
DEBUG_ERROR("%d:%s", errno, strerror(errno));
close(sock_nl);
return -1;
}
return 0;
}
static int init_socket(void)
{
struct sockaddr_in6 addr;
struct icmp6_filter filterv6;
int flags;
int opt = 1;
int err;
if ((sock_icmpv6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
{
DEBUG_ERROR("Create icmpv6 socket fail!\n");
return -1;
}
#if defined IPV6_PKTINFO && !defined IPV6_RECVPKTINFO
#define IPV6_RECVPKTINFO IPV6_PKTINFO
#endif
/* See RFC 3542 */
err = setsockopt(sock_icmpv6, IPPROTO_IPV6, IPV6_RECVPKTINFO, (int[]){1}, sizeof(int));
if(err)
DEBUG_ERROR("%d:%s", errno, strerror(errno));
ICMP6_FILTER_SETBLOCKALL(&filterv6);
ICMP6_FILTER_SETPASS
rtk处理ra报文流程
需积分: 5 35 浏览量
2023-07-19
14:41:11
上传
评论
收藏 9KB RAR 举报
kevin_0903
- 粉丝: 2
- 资源: 7
最新资源
- 本科毕业设计基于C# wpf人脸识别的考勤系统的设计与实现源码.zip
- 基于Ruoyi+uniapp实现学生考勤系统 学生考勤源码+项目说明.zip
- feae6bc968ca68a099455d8b8a8dea35
- 基于Pytorch训练CIRAR10上分类算法.zip
- Pytorch-pytorch深度学习教程之Tensorboard.zip
- 基于C++和Python开发yolov8-face作为人脸检测器dlib作为人脸识别器的人脸考勤系统源码+项目说明.zip
- Pytorch-pytorch深度学习教程之变分自动编码器.zip
- Pytorch-pytorch深度学习教程之神经风格迁移.zip
- Pytorch-pytorch深度学习教程之深度残差网络.zip
- Pytorch-pytorch深度学习教程之循环神经网络.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈