20200106_jeffrey - silenceuncrio/diary GitHub Wiki
review
結合以下這兩支來併成一支 gre_keepalive_06.c
- 每五秒發一次 gre tunnel keepalive request
gre_keepalive_05.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <linux/ip.h>
#include <linux/if.h>
struct grehdr {
u_int16_t flags;
u_int16_t protocol;
} __packed;
unsigned short csum(unsigned short *ptr,int nbytes) {
long sum;
unsigned short oddbyte;
short answer;
//Debug info
//hexdump((unsigned char *) ptr, nbytes);
//printf("csum nbytes: %d\n", nbytes);
//printf("csum ptr address: %p\n", ptr);
sum=0;
while(nbytes>1) {
sum+=*ptr++;
nbytes-=2;
}
if(nbytes==1) {
oddbyte=0;
*((u_char*)&oddbyte)=*(u_char*)ptr;
sum+=oddbyte;
}
sum = (sum>>16)+(sum & 0xffff);
sum = sum + (sum>>16);
answer=(short)~sum;
return(answer);
}
int main(int argc, char *argv[])
{
int sd;
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_GRE)) < 0) {
printf("socket() failed!\n");
return(1);
}
printf("OK: a raw socket with GRE protocol is created.\n");
#if 0
// inform the kernel do not fill up the packet structure, we will build our own
int one = 1;
const int *val = &one;
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
perror("setsockopt() error");
exit(2);
}
printf("OK: socket option IP_HDRINCL is set.\n");
#endif
#if 0
// bind raw socket to specific interface
const char *opt;
opt = "gre1";
const len = strnlen(opt, IFNAMSIZ);
if (len == IFNAMSIZ) {
fprintf(stderr, "Too long iface name");
return 1;
}
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, len);
printf("OK: socket option SO_BINDTODEVICE is set.\n");
#endif
struct sockaddr_in dest;
dest.sin_family = AF_INET;
if (inet_pton(AF_INET, "192.168.1.13", &(dest.sin_addr)) != 1) {
printf("Bad Address!\n");
return(1);
}
char buffer[128];
// let kernel decide the outer IP header
// fabricate the outer GRE header
struct grehdr *outer_greh = (struct grehdr *) buffer;
memset(outer_greh, 0, sizeof(struct grehdr));
outer_greh->protocol = 0x0800; // IP
// fabricate the inner IP header
struct iphdr *inner_ip = (struct iphdr *) (buffer + sizeof(struct grehdr));
memset(inner_ip, 0, sizeof(struct iphdr));
inner_ip->ihl = 5; // the number of 32-bit words in the header
inner_ip->version = 4; // IPv4
inner_ip->tos = 16; // low delay
inner_ip->tot_len = sizeof(struct iphdr) + sizeof(struct grehdr);
inner_ip->id = htons(0);
inner_ip->frag_off = 0x00;
inner_ip->ttl = 64;
inner_ip->protocol = 47; // GRE
inner_ip->check = 0; //16 bit checksum of IP header. Can't calculate at this point
inet_pton(AF_INET, "192.168.1.13", &(inner_ip->saddr));
inet_pton(AF_INET, "192.168.1.11", &(inner_ip->daddr));
// fabricate the inner GRE header
struct grehdr *inner_greh = (struct grehdr *) (buffer + sizeof(struct grehdr) + sizeof(struct iphdr));
memset(inner_greh, 0, sizeof(struct grehdr));
inner_greh->protocol = htons(0); // defined at cisco tunnel keepalive
// calculate the checksum for integrity
inner_ip->check = csum((unsigned short *) (buffer + sizeof(struct grehdr)), sizeof(struct iphdr) + sizeof(struct grehdr));
printf("checksum: 0x%04x\n", inner_ip->check);
if (sendto(sd, &buffer, sizeof(struct grehdr) + sizeof(struct iphdr) + sizeof(struct grehdr), 0,
(struct sockaddr*) &dest, sizeof(struct sockaddr)) < 0) {
printf("sendto() failed!\n");
return(1);
}
return(0);
}
tlpi_timers_ptmr_sigev_signal.c
/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2019. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/
#define _POSIX_C_SOURCE 199309
#include <signal.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define TIMER_SIG SIGRTMAX /* Our timer notification signal */
#define BUF_SIZE 1000
/* Return a string containing the current time formatted according to
the specification in 'format' (see strftime(3) for specifiers).
If 'format' is NULL, we use "%c" as a specifier (which gives the'
date and time as for ctime(3), but without the trailing newline).
Returns NULL on error. */
/* Convert a string of the following form to an itimerspec structure:
"value.sec[/value.nanosec][:interval.sec[/interval.nanosec]]".
Optional components that are omitted cause 0 to be assigned to the
corresponding structure fields. */
void
itimerspecFromStr(char *str, struct itimerspec *tsp)
{
char *dupstr ,*cptr, *sptr;
dupstr = strdup(str);
cptr = strchr(dupstr, ':');
if (cptr != NULL)
*cptr = '\0';
sptr = strchr(dupstr, '/');
if (sptr != NULL)
*sptr = '\0';
tsp->it_value.tv_sec = atoi(dupstr);
tsp->it_value.tv_nsec = (sptr != NULL) ? atoi(sptr + 1) : 0;
if (cptr == NULL) {
tsp->it_interval.tv_sec = 0;
tsp->it_interval.tv_nsec = 0;
} else {
sptr = strchr(cptr + 1, '/');
if (sptr != NULL)
*sptr = '\0';
tsp->it_interval.tv_sec = atoi(cptr + 1);
tsp->it_interval.tv_nsec = (sptr != NULL) ? atoi(sptr + 1) : 0;
}
free(dupstr);
}
char *
currTime(const char *format)
{
static char buf[BUF_SIZE]; /* Nonreentrant */
time_t t;
size_t s;
struct tm *tm;
t = time(NULL);
tm = localtime(&t);
if (tm == NULL)
return NULL;
s = strftime(buf, BUF_SIZE, (format != NULL) ? format : "%c", tm);
return (s == 0) ? NULL : buf;
}
static void
handler(int sig, siginfo_t *si, void *uc)
{
timer_t *tidptr;
tidptr = si->si_value.sival_ptr;
/* UNSAFE: This handler uses non-async-signal-safe functions
(printf(); see Section 21.1.2) */
printf("[%s] Got signal %d\n", currTime("%T"), sig);
printf(" *sival_ptr = %ld\n", (long) *tidptr);
printf(" timer_getoverrun() = %d\n", timer_getoverrun(*tidptr));
}
int
main(int argc, char *argv[])
{
struct itimerspec ts;
struct sigaction sa;
struct sigevent sev;
timer_t *tidlist;
int j;
if (argc < 2)
{
printf("%s secs[/nsecs][:int-secs[/int-nsecs]]...\n", argv[0]);
printf("usageErr: %s [secs [usecs [int-secs [int-usecs]]]]\n", argv[0]);
exit(EXIT_SUCCESS);
}
tidlist = calloc(argc - 1, sizeof(timer_t));
if (tidlist == NULL)
{
printf("errExit: malloc\n");
exit(EXIT_FAILURE);
}
/* Establish handler for notification signal */
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(TIMER_SIG, &sa, NULL) == -1)
{
printf("errExit: sigaction\n");
exit(EXIT_FAILURE);
}
/* Create and start one timer for each command-line argument */
sev.sigev_notify = SIGEV_SIGNAL; /* Notify via signal */
sev.sigev_signo = TIMER_SIG; /* Notify using this signal */
for (j = 0; j < argc - 1; j++) {
itimerspecFromStr(argv[j + 1], &ts);
sev.sigev_value.sival_ptr = &tidlist[j];
/* Allows handler to get ID of this timer */
if (timer_create(CLOCK_REALTIME, &sev, &tidlist[j]) == -1)
{
printf("errExit: timer_create\n");
exit(EXIT_FAILURE);
}
printf("Timer ID: %ld (%s)\n", (long) tidlist[j], argv[j + 1]);
if (timer_settime(tidlist[j], 0, &ts, NULL) == -1)
{
printf("errExit: timer_settime\n");
exit(EXIT_FAILURE);
}
}
for (;;) /* Wait for incoming timer signals */
pause();
}
搞定 - gre_keepalive_06.c
再來需要 pcap 來收取特定的 keepalive response
應該就是利用 src ip 以及 gre protocol type 這兩個欄位來收特定的 gre tunnel keepalive response
google libpcap tutorial
- Using libpcap in C
- The Sniffer's Guide to Raw Traffic
- Writing a Basic Packet Capture Engine
- Programming with pcap
- Programming with Libpcap - Sniffing the Network From Our Own Application
花點時間看一下 google 到的這幾篇
先大致 view 一下並為了這幾篇下幾個摘要再決定要花時間深入哪幾篇
-
Using libpcap in C
- 文章架構看起來還可以
- 也有 filter 的用法
-
The Sniffer's Guide to Raw Traffic
- 沒有 filter 的用法
-
Writing a Basic Packet Capture Engine
- 文章沒什麼編排
- 有 filter 的用法但沒什麼描述
-
Programming with pcap
- 簡單的官方教學文件
- 有 filter 的用法
-
Programming with Libpcap - Sniffing the Network From Our Own Application
- 刊登在雜誌上的文章
- 有 filter 的用法
簡單作個排序順邊把不要讀的刪掉
要開始花時間 study 了
-
Programming with pcap
- 簡單的官方教學文件
- 有 filter 的用法
-
Using libpcap in C
- 文章架構看起來還可以
- 也有 filter 的用法
- 有 filter 的用法但沒什麼描述
-
Programming with Libpcap - Sniffing the Network From Our Own Application
- 刊登在雜誌上的文章
- 有 filter 的用法
為了更容易使用 pcap
gre 的 config 欄位要多一個 device 的欄位
再幫忙修改 WAN > WiFi STA
web page
假使四周沒有任何 AP 的話
m330 會一直 scan 個不停
m330[release/v0.08] - at 'WAN > WiFi STA' web page, do not get the status until vm.status.scan_count != 0
commit c6ea949b90bf53ade1c859d9cd60beb0f31eea2b
Refs: [release/v0.08], {origin/release/v0.08}
Author: jeffrey <[email protected]>
Date: Mon Jan 6 13:28:49 2020 +0800
at 'WAN > WiFi STA' web page, do not get the status until vm.status.scan_count != 0
proscend/prosrc/www/app/feature/wifi_sta.js | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
在 study 官方教學文件 Programming with pcap 的過程
- 已經對 libpcap 不陌生了
- 應該不用看其他文件就可以開始 coding 了
時間還夠我再看一下 Using libpcap in C
參考 pcap-filter(7) - Linux man page
想辦法怎麼 filter 出 gre tunnel keepalive response
應該可以開始 coding 了