* Track MAC addresses in the client cache (when we can find them); so if we have an expired cache entry, but the MAC hasn't changed, we can assume the original ID is still valid.
This commit is contained in:
parent
780ae7ad8b
commit
51e61e3973
35
getifaddr.c
35
getifaddr.c
@ -127,3 +127,38 @@ getifhwaddr(const char * ifname, char * buf, int len)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_remote_mac(struct in_addr ip_addr, unsigned char * mac)
|
||||||
|
{
|
||||||
|
struct in_addr arp_ent;
|
||||||
|
FILE * arp;
|
||||||
|
char remote_ip[16];
|
||||||
|
int matches, hwtype, flags;
|
||||||
|
memset(mac, 0xFF, 6);
|
||||||
|
|
||||||
|
arp = fopen("/proc/net/arp", "r");
|
||||||
|
if( !arp )
|
||||||
|
return 1;
|
||||||
|
while( !feof(arp) )
|
||||||
|
{
|
||||||
|
matches = fscanf(arp, "%s 0x%X 0x%X %hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||||
|
remote_ip, &hwtype, &flags,
|
||||||
|
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
|
||||||
|
if( matches != 9 )
|
||||||
|
continue;
|
||||||
|
inet_pton(AF_INET, remote_ip, &arp_ent);
|
||||||
|
if( ip_addr.s_addr == arp_ent.s_addr )
|
||||||
|
break;
|
||||||
|
mac[0] = 0xFF;
|
||||||
|
}
|
||||||
|
fclose(arp);
|
||||||
|
|
||||||
|
if( mac[0] == 0xFF )
|
||||||
|
{
|
||||||
|
memset(mac, 0xFF, 6);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#ifndef __GETIFADDR_H__
|
#ifndef __GETIFADDR_H__
|
||||||
#define __GETIFADDR_H__
|
#define __GETIFADDR_H__
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
/* getifaddr()
|
/* getifaddr()
|
||||||
* take a network interface name and write the
|
* take a network interface name and write the
|
||||||
@ -20,5 +21,8 @@ getsysaddr(char * buf, int len);
|
|||||||
int
|
int
|
||||||
getifhwaddr(const char * ifname, char * buf, int len);
|
getifhwaddr(const char * ifname, char * buf, int len);
|
||||||
|
|
||||||
|
int
|
||||||
|
get_remote_mac(struct in_addr ip_addr, unsigned char * mac);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ struct album_art_name_s {
|
|||||||
|
|
||||||
struct client_cache_s {
|
struct client_cache_s {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
|
unsigned char mac[6];
|
||||||
enum client_types type;
|
enum client_types type;
|
||||||
u_int32_t flags;
|
u_int32_t flags;
|
||||||
time_t age;
|
time_t age;
|
||||||
|
33
upnphttp.c
33
upnphttp.c
@ -30,9 +30,11 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "upnpglobalvars.h"
|
#include "upnpglobalvars.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "getifaddr.h"
|
||||||
#include "image_utils.h"
|
#include "image_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sql.h"
|
#include "sql.h"
|
||||||
@ -94,11 +96,22 @@ SearchClientCache(struct in_addr addr)
|
|||||||
{
|
{
|
||||||
if( clients[i].addr.s_addr == addr.s_addr )
|
if( clients[i].addr.s_addr == addr.s_addr )
|
||||||
{
|
{
|
||||||
/* Invalidate this client cache if it's older than 2 hours */
|
/* Invalidate this client cache if it's older than 1 hour */
|
||||||
if( (time(NULL) - clients[i].age) > 7200 )
|
if( (time(NULL) - clients[i].age) > 3600 )
|
||||||
{
|
{
|
||||||
memset(&clients[i], 0, sizeof(struct client_cache_s));
|
unsigned char mac[6];
|
||||||
return -1;
|
if( get_remote_mac(addr, mac) == 0 &&
|
||||||
|
memcmp(mac, clients[i].mac, 6) == 0 )
|
||||||
|
{
|
||||||
|
/* Same MAC as last time when we were able to identify the client,
|
||||||
|
* so extend the timeout by another hour. */
|
||||||
|
clients[i].age = time(NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&clients[i], 0, sizeof(struct client_cache_s));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Client found in cache. [type %d/entry %d]\n", clients[i].type, i);
|
DPRINTF(E_DEBUG, L_HTTP, "Client found in cache. [type %d/entry %d]\n", clients[i].type, i);
|
||||||
return i;
|
return i;
|
||||||
@ -350,6 +363,9 @@ next_header:
|
|||||||
h->req_chunklen = -1;
|
h->req_chunklen = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Don't bother checking client type until we have the whole request. */
|
||||||
|
if( (h->req_buflen - h->req_contentoff) < h->req_contentlen )
|
||||||
|
return;
|
||||||
/* If the client type wasn't found, search the cache.
|
/* If the client type wasn't found, search the cache.
|
||||||
* This is done because a lot of clients like to send a
|
* This is done because a lot of clients like to send a
|
||||||
* different User-Agent with different types of requests. */
|
* different User-Agent with different types of requests. */
|
||||||
@ -363,15 +379,18 @@ next_header:
|
|||||||
{
|
{
|
||||||
if( clients[n].addr.s_addr )
|
if( clients[n].addr.s_addr )
|
||||||
continue;
|
continue;
|
||||||
|
get_remote_mac(h->clientaddr, clients[n].mac);
|
||||||
clients[n].addr = h->clientaddr;
|
clients[n].addr = h->clientaddr;
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "Added client [%d/%X] to cache slot %d.\n",
|
DPRINTF(E_DEBUG, L_HTTP, "Added client [%d/%s/%02X:%02X:%02X:%02X:%02X:%02X] to cache slot %d.\n",
|
||||||
h->req_client, clients[n].addr.s_addr, n);
|
h->req_client, inet_ntoa(clients[n].addr),
|
||||||
|
clients[n].mac[0], clients[n].mac[1], clients[n].mac[2],
|
||||||
|
clients[n].mac[3], clients[n].mac[4], clients[n].mac[5], n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( (n < EStandardDLNA150) && (h->req_client == EStandardDLNA150) )
|
else if( (n < EStandardDLNA150) && (h->req_client == EStandardDLNA150) )
|
||||||
{
|
{
|
||||||
/* If we know the client, but our new detection is generic, use our cached info */
|
/* If we know the client and our new detection is generic, use our cached info */
|
||||||
h->reqflags |= clients[n].flags;
|
h->reqflags |= clients[n].flags;
|
||||||
h->req_client = clients[n].type;
|
h->req_client = clients[n].type;
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user