1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/*
* filter.cpp: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <unistd.h>
#include "filter.h"
#undef WRITE_RAW
#if __GNUC__ > 3
#define UNUSED(v) UNUSED_ ## v __attribute__((unused))
#else
#define UNUSED(x) x
#endif
cFilterInfosatepg::cFilterInfosatepg(cGlobalInfosatepg *Global)
{
global = Global;
Set(global->Pid,0,0);
}
u_long cFilterInfosatepg::do_sum(u_long sum, u_char *buf, int nBytes)
{
int nleft=nBytes;
u_short *w = (u_short*)buf;
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if (nleft == 1)
{
u_short answer = 0;
*(u_char*)(&answer) = *(u_char*)w;
sum += answer;
}
return sum;
}
u_short cFilterInfosatepg::foldsum(u_long sum)
{
while (sum>>16)
sum = (sum >> 16) + (sum & 0xFFFF);
return ((u_short) ~sum);
}
u_short cFilterInfosatepg::IPChecksum(ip *ipHeader)
{
return foldsum(do_sum(0, (u_char*) ipHeader, sizeof(ip)));
} /* IpChecksum() */
u_short cFilterInfosatepg::UDPChecksum(ip *ipHeader, udphdr *udpHeader)
{
u_long sum = 0;
// Ip-Pseudo-Header
sum = do_sum(sum, (u_char*)(&ipHeader->ip_src), sizeof(ipHeader->ip_src));
sum = do_sum(sum, (u_char*)(&ipHeader->ip_dst), sizeof(ipHeader->ip_dst));
#ifdef __linux__
sum += udpHeader->len;
#else
sum += udpHeader->uh_ulen;
#endif
sum += ipHeader->ip_p<<8;
#ifdef __linux__
sum = do_sum(sum, (u_char*)udpHeader, ntohs(udpHeader->len));
#else
sum = do_sum(sum, (u_char*)udpHeader, ntohs(udpHeader->uh_ulen));
#endif
return foldsum(sum);
}
void cFilterInfosatepg::Process(u_short UNUSED(Pid), u_char UNUSED(Tid), const u_char *Data, int Length)
{
#define SECT_IP_HDR_START 12
#define SECT_UDP_HDR_START 32
#define SECT_IS_HDR_START 40
#define SECT_IS_DATA_START 52
if (Data[0]!=0x3E) return;
struct ether_header eth_hdr;
memset(ð_hdr,0,sizeof(struct ether_header));
eth_hdr.ether_dhost[0]=Data[11];
eth_hdr.ether_dhost[1]=Data[10];
eth_hdr.ether_dhost[2]=Data[9];
eth_hdr.ether_dhost[3]=Data[8];
eth_hdr.ether_dhost[4]=Data[4];
eth_hdr.ether_dhost[5]=Data[3];
// check mac and range
if (!global->CheckMAC(ð_hdr)) return;
int mac = eth_hdr.ether_dhost[5];
global->ActualMac=mac;
struct ip *ip_hdr = (ip *) &Data[SECT_IP_HDR_START];
struct udphdr *udp_hdr = (udphdr *) &Data[SECT_UDP_HDR_START];
// Only IPv4
if (ip_hdr->ip_v!=4) return;
// Check IP checksum
if (IPChecksum(ip_hdr)!=0)
{
esyslog("infosatepg: ip checksum error");
return;
}
// Only UDP
if (ip_hdr->ip_p!=17) return;
// Check UDP checksum
if (UDPChecksum(ip_hdr,udp_hdr)!=0)
{
esyslog("infosatepg: udp checksum error");
return;
}
struct infosathdr *ishdr = (struct infosathdr*) &Data[SECT_IS_HDR_START];
if (ntohs(ishdr->technisatId)!=0x0001) return;
int pktnr = ntohs(ishdr->pktnr);
int pktcnt = ntohs(ishdr->pktcnt);
const u_char *infosatdata = &Data[SECT_IS_DATA_START];
int len = Length - SECT_IS_DATA_START-4;
char file[1024];
snprintf(file,sizeof(file),"%s/infosatepg%02i%02i_%03i.dat",global->Directory(),ishdr->day,ishdr->month,
pktcnt);
if (global->Infosatdata[mac].NeverSeen(ishdr->day,ishdr->month,pktcnt))
{
// never seen such a packet -> init structure
global->Infosatdata[mac].Init(file,ishdr->day,ishdr->month,pktcnt);
}
// Check if we missed a packet
global->Infosatdata[mac].CheckMissed(pktnr);
// Check if we already have this packet
if (global->Infosatdata[mac].GetBit(pktnr))
{
global->Infosatdata[mac].SetLastPkt(pktnr);
return;
}
#ifdef VDRDEBUG
dsyslog("infosatepg: mac=%02x-%02x-%02x-%02x-%02x-%02x",eth_hdr.ether_dhost[0],eth_hdr.ether_dhost[1],
eth_hdr.ether_dhost[2],eth_hdr.ether_dhost[3],eth_hdr.ether_dhost[4],eth_hdr.ether_dhost[5] );
dsyslog("infosatepg: tid=%04i tbl=%04i stbl=%04i day=%02i month=%02i pktnr=%03i pktcnt=%03i len=%i",
ntohs(ishdr->technisatId),ishdr->tableId,ishdr->tablesubId,ishdr->day,
ishdr->month, pktnr, pktcnt, len);
dsyslog("infosatepg: save to %s", file);
#endif
int f=open(file,O_RDWR|O_CREAT,0664);
if (f==-1)
{
if (errno!=ENOSPC)
{
esyslog("infosatepg: unable to create file '%s'", file);
}
return;
}
off_t offset = (off_t) (pktnr*1400);
if (lseek(f,offset,SEEK_SET)!=(off_t) -1)
{
#ifdef VDRDEBUG
dsyslog("infosatepg: writing to %li",offset);
#endif
if (write(f,infosatdata,len)==len)
{
// set bit in Infosatdata bitfield
global->Infosatdata[mac].SetBit(pktnr,true);
}
}
close(f);
#ifdef WRITE_RAW
sprintf(file,"%s/%03i.dat",dir,pktnr);
f=open(file,O_RDWR|O_CREAT,0664);
if (f==-1) return;
write(f,Data,Length);
close(f);
#endif
// check if we have all packets
if (global->Infosatdata[mac].CheckReceivedAll())
{
// we have all packets
isyslog("infosatepg: day=%02i month=%02i fully received", ishdr->day,ishdr->month);
}
}
|