Adding minissdpd
This commit is contained in:
parent
0d96346588
commit
d535e18678
|
@ -0,0 +1,59 @@
|
|||
$Id: Changelog.txt,v 1.19 2011/07/30 13:16:22 nanard Exp $
|
||||
|
||||
VERSION 1.1:
|
||||
|
||||
2011/07/30:
|
||||
fixes. More overflow checks
|
||||
|
||||
2011/07/29:
|
||||
added a lot of buffer overflow checks. Check malloc() failure, etc.
|
||||
Better cleanup in case of crash at start.
|
||||
network interface watch to add/drop multicast membership when the interface get live.
|
||||
|
||||
2011/06/18:
|
||||
Starting to add support for UPnP Device Architecture v1.1
|
||||
|
||||
2011/05/23:
|
||||
Added IPv6 support.
|
||||
-i option now understands interface names as well as addresses.
|
||||
|
||||
VERSION 1.0:
|
||||
|
||||
2008/10/07:
|
||||
added codelength.h
|
||||
Fixing response to M-SEARCH
|
||||
Doc update
|
||||
|
||||
2008/10/06:
|
||||
UPnP server support (answering M-SEARCH)
|
||||
|
||||
2008/10/04:
|
||||
listening on several interfaces.
|
||||
|
||||
2008/10/01:
|
||||
use of daemon() instead of home made daemonize.
|
||||
|
||||
2007/12/19:
|
||||
added uuid in responses
|
||||
3 types of requests supported.
|
||||
preventing buffer overflow
|
||||
|
||||
2007/12/18:
|
||||
It is now possible to change the location of both pid file and
|
||||
unix socket.
|
||||
|
||||
2007/10/08:
|
||||
Added a man page
|
||||
|
||||
2007/09/27:
|
||||
Support for install in different location $ PREFIX=... make install
|
||||
|
||||
2007/09/23:
|
||||
added a script for use in /etc/init.d
|
||||
improved Makefile
|
||||
creating /var/run/minissdpd.pid
|
||||
adding synthetic messages for new devices/removed devices
|
||||
|
||||
2007/09/19:
|
||||
Take SSDP announce packets lifetime into account.
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2007-2009, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# $Id: Makefile,v 1.13 2011/07/29 15:21:12 nanard Exp $
|
||||
# MiniUPnP project
|
||||
# author: Thomas Bernard
|
||||
# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
# for use with GNU Make (gmake)
|
||||
# install with :
|
||||
# $ PREFIX=/tmp/dummylocation make install
|
||||
# or
|
||||
# $ INSTALLPREFIX=/usr/local make install
|
||||
# or
|
||||
# make install (miniupnpd will be put in /usr/sbin)
|
||||
#
|
||||
# install target is made for linux... sorry BSD users...
|
||||
#CFLAGS = -Wall -g -D_GNU_SOURCE -Wstrict-prototypes
|
||||
CFLAGS = -Wall -Os -D_GNU_SOURCE -fno-strict-aliasing -Wstrict-prototypes
|
||||
CC = gcc
|
||||
RM = rm -f
|
||||
INSTALL = install
|
||||
|
||||
#EXECUTABLES = minissdpd testminissdpd listifaces
|
||||
EXECUTABLES = minissdpd testminissdpd testcodelength
|
||||
MINISSDPDOBJS = minissdpd.o openssdpsocket.o daemonize.o upnputils.o ifacewatch.o
|
||||
TESTMINISSDPDOBJS = testminissdpd.o
|
||||
|
||||
ALLOBJS = $(MINISSDPDOBJS) $(TESTMINISSDPDOBJS) testcodelength.o
|
||||
|
||||
INSTALLPREFIX ?= $(PREFIX)/usr
|
||||
SBININSTALLDIR = $(INSTALLPREFIX)/sbin
|
||||
|
||||
.PHONY: all clean install depend
|
||||
|
||||
all: $(EXECUTABLES)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALLOBJS) $(EXECUTABLES)
|
||||
|
||||
install: minissdpd
|
||||
$(INSTALL) -d $(SBININSTALLDIR)
|
||||
$(INSTALL) minissdpd $(SBININSTALLDIR)
|
||||
$(INSTALL) -d $(PREFIX)/etc/init.d
|
||||
$(INSTALL) minissdpd.init.d.script $(PREFIX)/etc/init.d/minissdpd
|
||||
|
||||
minissdpd: $(MINISSDPDOBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(MINISSDPDOBJS)
|
||||
|
||||
testminissdpd: $(TESTMINISSDPDOBJS)
|
||||
|
||||
testcodelength: testcodelength.o
|
||||
|
||||
depend:
|
||||
makedepend -f$(MAKEFILE_LIST) -Y \
|
||||
$(ALLOBJS:.o=.c) 2>/dev/null
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
minissdpd.o: config.h upnputils.h openssdpsocket.h daemonize.h codelength.h
|
||||
minissdpd.o: ifacewatch.h
|
||||
openssdpsocket.o: config.h openssdpsocket.h
|
||||
daemonize.o: daemonize.h config.h
|
||||
upnputils.o: config.h upnputils.h
|
||||
ifacewatch.o: config.h openssdpsocket.h
|
||||
testcodelength.o: codelength.h
|
|
@ -0,0 +1,36 @@
|
|||
protocole :
|
||||
|
||||
connection à la socket unix.
|
||||
envoie d'une requete, retour d'une reponse.
|
||||
fermeture de la connexion.
|
||||
|
||||
format de requete :
|
||||
1 octet : type de la requete
|
||||
1 - type
|
||||
2 - USN (id unique)
|
||||
3 - tout
|
||||
n octets longueur de la chaine : 1 octet si < 128 sinon le bit haut
|
||||
indique s'il existe un octet suplementaire, etc...
|
||||
n octets = chaine
|
||||
|
||||
format reponse :
|
||||
1 octet : nombre de reponses
|
||||
pour chaque rep :
|
||||
URL :
|
||||
n octets longueur de la chaine
|
||||
n octets = chaine Location
|
||||
ST:
|
||||
n octets longueur de la chaine
|
||||
n octets = chaine type
|
||||
USN:
|
||||
n octets longueur de la chaine
|
||||
n octets = chaine identifiant
|
||||
|
||||
Type de requete 4 = submit service
|
||||
1 octet = 4
|
||||
(k,n) octets : longueur et chaine "ST" (service type)
|
||||
(k,n) octets : longueur et chaine "USN"
|
||||
(k,n) octets : longueur et chaine "Server"
|
||||
(k,n) octets : longueur et chaine "Location"
|
||||
Pas de reponse
|
||||
|
|
@ -0,0 +1 @@
|
|||
1.1
|
|
@ -0,0 +1,31 @@
|
|||
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2011 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#ifndef __CODELENGTH_H__
|
||||
#define __CODELENGTH_H__
|
||||
|
||||
/* Encode length by using 7bit per Byte :
|
||||
* Most significant bit of each byte specifies that the
|
||||
* following byte is part of the code */
|
||||
#define DECODELENGTH(n, p) n = 0; \
|
||||
do { n = (n << 7) | (*p & 0x7f); } \
|
||||
while((*(p++)&0x80) && (n<(1<<25)));
|
||||
|
||||
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
|
||||
n = 0; \
|
||||
do { \
|
||||
if((p) >= (p_limit)) break; \
|
||||
n = (n << 7) | (*(p) & 0x7f); \
|
||||
} while((*((p)++)&0x80) && (n<(1<<25)));
|
||||
|
||||
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
|
||||
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
|
||||
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
|
||||
if(n>=128) *(p++) = (n >> 7) | 0x80; \
|
||||
*(p++) = n & 0x7f;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* $Id: config.h,v 1.4 2011/05/23 12:22:29 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#ifndef __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
/* use BSD daemon() ? */
|
||||
#define USE_DAEMON
|
||||
|
||||
/* set the syslog facility to use. See man syslog(3) and syslog.conf(5). */
|
||||
#define LOG_MINISSDPD LOG_DAEMON
|
||||
|
||||
/* enable IPv6 */
|
||||
#define ENABLE_IPV6
|
||||
|
||||
/* Maximum number of network interface we can listen on */
|
||||
#define MAX_IF_ADDR 8
|
||||
|
||||
#endif
|
|
@ -0,0 +1,129 @@
|
|||
/* $Id: daemonize.c,v 1.12 2011/05/27 09:35:02 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "daemonize.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifndef USE_DAEMON
|
||||
|
||||
int
|
||||
daemonize(void)
|
||||
{
|
||||
int pid, i;
|
||||
|
||||
switch(fork())
|
||||
{
|
||||
/* fork error */
|
||||
case -1:
|
||||
perror("fork()");
|
||||
exit(1);
|
||||
|
||||
/* child process */
|
||||
case 0:
|
||||
/* obtain a new process group */
|
||||
if( (pid = setsid()) < 0)
|
||||
{
|
||||
perror("setsid()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* close all descriptors */
|
||||
for (i=getdtablesize();i>=0;--i) close(i);
|
||||
|
||||
i = open("/dev/null", O_RDWR); /* open stdin */
|
||||
dup(i); /* stdout */
|
||||
dup(i); /* stderr */
|
||||
|
||||
umask(027);
|
||||
chdir("/"); /* chdir to /tmp ? */
|
||||
|
||||
return pid;
|
||||
|
||||
/* parent process */
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
writepidfile(const char * fname, int pid)
|
||||
{
|
||||
char pidstring[16];
|
||||
int pidstringlen;
|
||||
int pidfile;
|
||||
|
||||
if(!fname || (strlen(fname) == 0))
|
||||
return -1;
|
||||
|
||||
if( (pidfile = open(fname, O_WRONLY|O_CREAT, 0644)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to open pidfile for writing %s: %m", fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid);
|
||||
if(pidstringlen <= 0)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
"Unable to write to pidfile %s: snprintf(): FAILED", fname);
|
||||
close(pidfile);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(write(pidfile, pidstring, pidstringlen) < 0)
|
||||
syslog(LOG_ERR, "Unable to write to pidfile %s: %m", fname);
|
||||
}
|
||||
|
||||
close(pidfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
checkforrunning(const char * fname)
|
||||
{
|
||||
char buffer[64];
|
||||
int pidfile;
|
||||
pid_t pid;
|
||||
|
||||
if(!fname || (strlen(fname) == 0))
|
||||
return -1;
|
||||
|
||||
if( (pidfile = open(fname, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
|
||||
memset(buffer, 0, 64);
|
||||
|
||||
if(read(pidfile, buffer, 63))
|
||||
{
|
||||
if( (pid = atol(buffer)) > 0)
|
||||
{
|
||||
if(!kill(pid, 0))
|
||||
{
|
||||
close(pidfile);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(pidfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* $Id: daemonize.h,v 1.6 2008/01/29 13:04:46 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef __DAEMONIZE_H__
|
||||
#define __DAEMONIZE_H__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef USE_DAEMON
|
||||
/* daemonize()
|
||||
* "fork" to background, detach from terminal, etc...
|
||||
* returns: pid of the daemon, exits upon failure */
|
||||
int
|
||||
daemonize(void);
|
||||
#endif
|
||||
|
||||
/* writepidfile()
|
||||
* write the pid to a file */
|
||||
int
|
||||
writepidfile(const char * fname, int pid);
|
||||
|
||||
/* checkforrunning()
|
||||
* check for another instance running
|
||||
* returns: 0 only instance
|
||||
* -1 invalid filename
|
||||
* -2 another instance running */
|
||||
int
|
||||
checkforrunning(const char * fname);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/* $Id: ifacewatch.c,v 1.2 2011/07/30 13:10:05 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* (c) 2011 Thomas Bernard
|
||||
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#else /* __linux__ */
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
#include <syslog.h>
|
||||
|
||||
#include "openssdpsocket.h"
|
||||
|
||||
int
|
||||
OpenAndConfInterfaceWatchSocket(void)
|
||||
{
|
||||
int s;
|
||||
#ifdef __linux__
|
||||
struct sockaddr_nl addr;
|
||||
|
||||
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
#else /* __linux__*/
|
||||
/*s = socket(PF_ROUTE, SOCK_RAW, AF_INET);*/
|
||||
s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||
/* The family parameter may be AF_UNSPEC which will provide routing informa-
|
||||
* tion for all address families, or can be restricted to a specific address
|
||||
* family by specifying which one is desired. There can be more than one
|
||||
* routing socket open per system. */
|
||||
#endif
|
||||
if(s < 0) {
|
||||
syslog(LOG_ERR, "OpenAndConfInterfaceWatchSocket socket: %m");
|
||||
return -1;
|
||||
}
|
||||
#ifdef __linux__
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
syslog(LOG_ERR, "bind(netlink): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the message and add/drop multicast membership if needed
|
||||
*/
|
||||
int
|
||||
ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6,
|
||||
int n_if_addr, const char * * if_addr)
|
||||
{
|
||||
ssize_t len;
|
||||
int i;
|
||||
char buffer[4096];
|
||||
#ifdef __linux__
|
||||
struct iovec iov;
|
||||
struct msghdr hdr;
|
||||
struct nlmsghdr *nlhdr;
|
||||
struct ifaddrmsg *ifa;
|
||||
|
||||
iov.iov_base = buffer;
|
||||
iov.iov_len = sizeof(buffer);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = &iov;
|
||||
hdr.msg_iovlen = 1;
|
||||
|
||||
len = recvmsg(s, &hdr, 0);
|
||||
if(len < 0) {
|
||||
syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(nlhdr = (struct nlmsghdr *)buffer;
|
||||
NLMSG_OK(nlhdr, len);
|
||||
nlhdr = NLMSG_NEXT(nlhdr, len)) {
|
||||
syslog(LOG_DEBUG, "nlmsg_type=%d", nlhdr->nlmsg_type);
|
||||
if(nlhdr->nlmsg_type == NLMSG_DONE)
|
||||
break;
|
||||
if(nlhdr->nlmsg_type == RTM_NEWADDR) {
|
||||
ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
|
||||
syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifa->ifa_index);
|
||||
for(i = 0; i < n_if_addr; i++) {
|
||||
if(ifa->ifa_index == if_nametoindex(if_addr[i])) {
|
||||
AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(nlhdr->nlmsg_type == RTM_DELADDR) {
|
||||
ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
|
||||
syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifa->ifa_index);
|
||||
for(i = 0; i < n_if_addr; i++) {
|
||||
if(ifa->ifa_index == if_nametoindex(if_addr[i])) {
|
||||
AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* __linux__ */
|
||||
struct rt_msghdr * rtm;
|
||||
struct ifa_msghdr * ifam;
|
||||
|
||||
len = recv(s, buffer, sizeof(buffer), 0);
|
||||
if(len < 0) {
|
||||
syslog(LOG_ERR, "ProcessInterfaceWatchNotify recv: %m");
|
||||
return -1;
|
||||
}
|
||||
rtm = (struct rt_msghdr *)buffer;
|
||||
switch(rtm->rtm_type) {
|
||||
case RTM_NEWADDR:
|
||||
ifam = (struct ifa_msghdr *)buffer;
|
||||
syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifam->ifam_index);
|
||||
for(i = 0; i < n_if_addr; i++) {
|
||||
if(ifam->ifam_index == if_nametoindex(if_addr[i])) {
|
||||
AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RTM_DELADDR:
|
||||
ifam = (struct ifa_msghdr *)buffer;
|
||||
syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifam->ifam_index);
|
||||
for(i = 0; i < n_if_addr; i++) {
|
||||
if(ifam->ifam_index == if_nametoindex(if_addr[i])) {
|
||||
/* I dont think it is useful */
|
||||
/*AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1);*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_DEBUG, "rtm->rtm_type=%d", rtm->rtm_type);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* $Id: ifacewatch.h,v 1.1 2011/07/29 15:21:13 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef __IFACEWATCH_H__
|
||||
#define __IFACEWATCH_H__
|
||||
|
||||
int
|
||||
OpenAndConfInterfaceWatchSocket(void);
|
||||
|
||||
int
|
||||
ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6,
|
||||
int n_if_addr, const char * * if_addr);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,79 @@
|
|||
/* $Id: listifaces.c,v 1.4 2007/09/23 16:59:02 nanard Exp $ */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void printhex(const unsigned char * p, int n)
|
||||
{
|
||||
int i;
|
||||
while(n>0)
|
||||
{
|
||||
for(i=0; i<16; i++)
|
||||
printf("%02x ", p[i]);
|
||||
printf("| ");
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
putchar((p[i]>=32 && p[i]<127)?p[i]:'.');
|
||||
}
|
||||
printf("\n");
|
||||
p+=16;
|
||||
n -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
void listifaces()
|
||||
{
|
||||
struct ifconf ifc;
|
||||
char * buf = 0;
|
||||
int buflen = sizeof(struct ifreq)*20;
|
||||
/*[sizeof(struct ifreq)*8];*/
|
||||
int s, i;
|
||||
int j;
|
||||
char saddr[256/*INET_ADDRSTRLEN*/];
|
||||
/*s = socket(PF_INET, SOCK_DGRAM, 0);*/
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
do {
|
||||
buflen += buflen;
|
||||
buf = realloc(buf, buflen);
|
||||
ifc.ifc_len = buflen;
|
||||
ifc.ifc_buf = (caddr_t)buf;
|
||||
if(ioctl(s, SIOCGIFCONF, &ifc) < 0)
|
||||
{
|
||||
perror("ioctl");
|
||||
close(s);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
printf("%d - %d - %d\n", buflen, ifc.ifc_len, (int)sizeof(struct ifreq));
|
||||
printf(" %d\n", IFNAMSIZ);
|
||||
printf(" %d %d\n", (int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) );
|
||||
} while(buflen == ifc.ifc_len);
|
||||
printhex((const unsigned char *)ifc.ifc_buf, ifc.ifc_len);
|
||||
j = 0;
|
||||
for(i=0; i<ifc.ifc_len; /*i += sizeof(struct ifreq)*/)
|
||||
{
|
||||
//const struct ifreq * ifrp = &(ifc.ifc_req[j]);
|
||||
const struct ifreq * ifrp = (const struct ifreq *)(buf + i);
|
||||
i += sizeof(ifrp->ifr_name) + 16;//ifrp->ifr_addr.sa_len;
|
||||
/*inet_ntop(AF_INET, &(((struct sockaddr_in *)&(ifrp->ifr_addr))->sin_addr), saddr, sizeof(saddr));*/
|
||||
saddr[0] = '\0';
|
||||
inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr));
|
||||
printf("%2d %d %d %s %s\n", j, ifrp->ifr_addr.sa_family, -1/*ifrp->ifr_addr.sa_len*/, ifrp->ifr_name, saddr);
|
||||
j++;
|
||||
}
|
||||
free(buf);
|
||||
close(s);
|
||||
}
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
listifaces();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
.TH "minissdpd" 1
|
||||
.SH NAME
|
||||
minissdpd \- daemon keeping track of UPnP devices up
|
||||
.SH SYNOPSIS
|
||||
.B minissdpd
|
||||
[-d] [-s socket] [-p pidfile] -i address [-i address] ...
|
||||
.SH DESCRIPTION
|
||||
minissdpd listen for SSDP traffic and keeps track
|
||||
of what are the UPnP devices up on the network.
|
||||
The list of the UPnP devices is accessed by programs
|
||||
looking for devices, skipping the UPnP discovery process.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-d
|
||||
debug : do not go to background, output messages to console
|
||||
and do not filter out low priority messages.
|
||||
.TP
|
||||
.B \-6
|
||||
IPv6 : Enable IPv6 in addition to IPv4.
|
||||
.TP
|
||||
.B \-s socket
|
||||
path of the unix socket open for communicating with other processes.
|
||||
By default /var/run/minissdpd.sock is used.
|
||||
.TP
|
||||
.B \-p pidfile
|
||||
path of the file where pid is written at startup.
|
||||
By default /var/run/minissdpd.pid is used.
|
||||
.TP
|
||||
.B \-i interface
|
||||
name or IP address of the interface used to listen to SSDP packets
|
||||
comming on port 1900, multicast address 239.255.255.250.
|
||||
.SH "SEE ALSO"
|
||||
miniupnpd(1) miniupnpc(3)
|
||||
.SH BUGS
|
||||
No known bugs.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
# $Id: minissdpd.init.d.script,v 1.2 2007/09/23 17:46:57 nanard Exp $
|
||||
# MiniUPnP project
|
||||
# author: Thomas Bernard
|
||||
# website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
|
||||
MINISSDPD=/usr/sbin/minissdpd
|
||||
PIDFILE=/var/run/minissdpd.pid
|
||||
# get default interface
|
||||
IF=`route | grep default |awk -- '{ print $8 }'`
|
||||
ARGS="-i `ifconfig $IF|grep 'inet adr'|sed 's/.\+inet adr:\([0-9.]\+\).\+/\1/'`"
|
||||
|
||||
test -f $MINISSDPD || exit 0
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
case "$1" in
|
||||
start) log_daemon_msg "Starting minissdpd" "minissdpd"
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
||||
--exec $MINISSDPD -- $ARGS $LSBNAMES
|
||||
log_end_msg $?
|
||||
;;
|
||||
stop) log_daemon_msg "Stopping minissdpd" "minissdpd"
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE
|
||||
log_end_msg $?
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
log_daemon_msg "Restarting minissdpd" "minissdpd"
|
||||
start-stop-daemon --stop --retry 5 --quiet --pidfile $PIDFILE
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE \
|
||||
--exec $MINISSDPD -- $ARGS $LSBNAMES
|
||||
log_end_msg $?
|
||||
;;
|
||||
*) log_action_msg "Usage: /etc/init.d/minissdpd {start|stop|restart|reload|force-reload}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/* $Id: openssdpsocket.c,v 1.7 2011/07/30 13:10:06 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "openssdpsocket.h"
|
||||
|
||||
/* SSDP ip/port */
|
||||
#define SSDP_PORT (1900)
|
||||
#define SSDP_MCAST_ADDR ("239.255.255.250")
|
||||
/* Link Local and Site Local SSDP IPv6 multicast addresses */
|
||||
#define LL_SSDP_MCAST_ADDR ("FF02::C")
|
||||
#define SL_SSDP_MCAST_ADDR ("FF05::C")
|
||||
|
||||
/**
|
||||
* Get the IPv4 address from a string
|
||||
* representing the address or the interface name
|
||||
*/
|
||||
static in_addr_t
|
||||
GetIfAddrIPv4(const char * ifaddr)
|
||||
{
|
||||
in_addr_t addr;
|
||||
int s;
|
||||
struct ifreq ifr;
|
||||
int ifrlen;
|
||||
|
||||
/* let's suppose ifaddr is a IPv4 address
|
||||
* such as 192.168.1.1 */
|
||||
addr = inet_addr(ifaddr);
|
||||
if(addr != INADDR_NONE)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
/* let's suppose the ifaddr was in fact an interface name
|
||||
* such as eth0 */
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "socket(PF_INET, SOCK_DGRAM): %m");
|
||||
return INADDR_NONE;
|
||||
}
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
strncpy(ifr.ifr_name, ifaddr, IFNAMSIZ);
|
||||
if(ioctl(s, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
|
||||
close(s);
|
||||
return INADDR_NONE;
|
||||
}
|
||||
syslog(LOG_DEBUG, "GetIfAddrIPv4(%s) = %s", ifaddr,
|
||||
inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
|
||||
addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
||||
close(s);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the multicast membership for SSDP on the interface
|
||||
* @param s the socket
|
||||
* @param ifaddr the IPv4 address or interface name
|
||||
* @param ipv6 IPv6 or IPv4
|
||||
* return -1 on error, 0 on success */
|
||||
int
|
||||
AddDropMulticastMembership(int s, const char * ifaddr, int ipv6, int drop)
|
||||
{
|
||||
struct ip_mreq imr; /* Ip multicast membership */
|
||||
#ifdef ENABLE_IPV6
|
||||
struct ipv6_mreq mr;
|
||||
unsigned int ifindex;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
if(ipv6)
|
||||
{
|
||||
ifindex = if_nametoindex(ifaddr);
|
||||
memset(&mr, 0, sizeof(mr));
|
||||
inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr);
|
||||
mr.ipv6mr_interface = ifindex;
|
||||
if(setsockopt(s, IPPROTO_IPV6, drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP,
|
||||
&mr, sizeof(struct ipv6_mreq)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp, %s)(%s): %m",
|
||||
drop ? "IPV6_LEAVE_GROUP" : "IPV6_JOIN_GROUP",
|
||||
ifaddr);
|
||||
return -1;
|
||||
}
|
||||
inet_pton(AF_INET6, SL_SSDP_MCAST_ADDR, &mr.ipv6mr_multiaddr);
|
||||
if(setsockopt(s, IPPROTO_IPV6, drop ? IPV6_LEAVE_GROUP : IPV6_JOIN_GROUP,
|
||||
&mr, sizeof(struct ipv6_mreq)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp, %s)(%s): %m",
|
||||
drop ? "IPV6_LEAVE_GROUP" : "IPV6_JOIN_GROUP",
|
||||
ifaddr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
/* setting up imr structure */
|
||||
imr.imr_multiaddr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
/*imr.imr_interface.s_addr = htonl(INADDR_ANY);*/
|
||||
/*imr.imr_interface.s_addr = inet_addr(ifaddr);*/
|
||||
imr.imr_interface.s_addr = GetIfAddrIPv4(ifaddr);
|
||||
if(imr.imr_interface.s_addr == INADDR_NONE)
|
||||
{
|
||||
syslog(LOG_ERR, "no IPv4 address for interface %s",
|
||||
ifaddr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(s, IPPROTO_IP, drop ? IP_DROP_MEMBERSHIP : IP_ADD_MEMBERSHIP,
|
||||
(void *)&imr, sizeof(struct ip_mreq)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp, %s)(%s): %m",
|
||||
drop ? "IP_DROP_MEMBERSHIP" : "IP_ADD_MEMBERSHIP",
|
||||
ifaddr);
|
||||
return -1;
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
OpenAndConfSSDPReceiveSocket(int n_listen_addr,
|
||||
const char * * listen_addr,
|
||||
int ipv6)
|
||||
{
|
||||
int s;
|
||||
#ifdef ENABLE_IPV6
|
||||
int on = 1;
|
||||
struct sockaddr_storage sockname;
|
||||
#else
|
||||
struct sockaddr_in sockname;
|
||||
#endif
|
||||
socklen_t sockname_len;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
if( (s = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
#else
|
||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
#endif
|
||||
{
|
||||
syslog(LOG_ERR, "socket(udp): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_storage));
|
||||
if(ipv6)
|
||||
{
|
||||
#ifdef IPV6_V6ONLY
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(char *)&on, sizeof(on)) < 0)
|
||||
{
|
||||
syslog(LOG_WARNING, "setsockopt(IPV6_V6ONLY): %m");
|
||||
}
|
||||
#endif
|
||||
struct sockaddr_in6 * sa = (struct sockaddr_in6 *)&sockname;
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_port = htons(SSDP_PORT);
|
||||
sa->sin6_addr = in6addr_any;
|
||||
sockname_len = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in * sa = (struct sockaddr_in *)&sockname;
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_port = htons(SSDP_PORT);
|
||||
sa->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
sockname_len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
#else
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_port = htons(SSDP_PORT);
|
||||
/* NOTE : it seems it doesnt work when binding on the specific address */
|
||||
/*sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/
|
||||
sockname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
/*sockname.sin_addr.s_addr = inet_addr(ifaddr);*/
|
||||
sockname_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
|
||||
if(bind(s, (struct sockaddr *)&sockname, sockname_len) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "bind(udp%s): %m", ipv6 ? "6" : "");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(n_listen_addr>0)
|
||||
{
|
||||
n_listen_addr--;
|
||||
if(AddDropMulticastMembership(s, listen_addr[n_listen_addr], ipv6, 0) < 0)
|
||||
{
|
||||
syslog(LOG_WARNING, "Failed to add IPv%d multicast membership for interface %s.",
|
||||
ipv6 ? 6 : 4,
|
||||
listen_addr[n_listen_addr] );
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/* $Id: openssdpsocket.h,v 1.4 2011/07/29 15:21:13 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
#ifndef __OPENSSDPSOCKET_H__
|
||||
#define __OPENSSDPSOCKET_H__
|
||||
|
||||
/**
|
||||
* Open a socket and configure it for receiving SSDP packets
|
||||
*
|
||||
* @param n_listen_addr size of listen_addr array
|
||||
* @param listen_addr array of address (or interface names) to listen
|
||||
* @param ipv6 open INET6 or INET socket
|
||||
* @return socket
|
||||
*/
|
||||
int
|
||||
OpenAndConfSSDPReceiveSocket(int n_if_addr,
|
||||
const char * * if_addr,
|
||||
int ipv6);
|
||||
|
||||
/**
|
||||
* Add or Drop the multicast membership for SSDP on the interface
|
||||
* @param s the socket
|
||||
* @param ifaddr the IPv4 address or interface name
|
||||
* @param ipv6 IPv6 or IPv4
|
||||
* @param drop 0 to add, 1 to drop
|
||||
* return -1 on error, 0 on success */
|
||||
int
|
||||
AddDropMulticastMembership(int s, const char * ifaddr, int ipv6, int drop);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* $Id: testcodelength.c,v 1.2 2011/06/17 23:05:00 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2008 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <stdio.h>
|
||||
#include "codelength.h"
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
unsigned char buf[256];
|
||||
unsigned char * p;
|
||||
long i, j;
|
||||
|
||||
for(i = 1; i < 1000000000; i *= 2) {
|
||||
/* encode i, decode to j */
|
||||
printf("%ld ", i);
|
||||
p = buf;
|
||||
CODELENGTH(i, p);
|
||||
p = buf;
|
||||
DECODELENGTH(j, p);
|
||||
if(i != j) {
|
||||
fprintf(stderr, "Error ! encoded %ld, decoded %ld.\n", i, j);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
printf("Test succesful\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/* $Id: testminissdpd.c,v 1.6 2007/12/19 14:49:30 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2007 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define DECODELENGTH(n, p) n = 0; \
|
||||
do { n = (n << 7) | (*p & 0x7f); } \
|
||||
while(*(p++)&0x80);
|
||||
|
||||
void printresponse(const unsigned char * resp, int n)
|
||||
{
|
||||
int i, l;
|
||||
unsigned int nresp;
|
||||
const unsigned char * p;
|
||||
for(i=0; i<n; i++)
|
||||
printf("%02x ", resp[i]);
|
||||
printf("\n");
|
||||
nresp = resp[0];
|
||||
p = resp + 1;
|
||||
for(i = 0; i < nresp; i++) {
|
||||
/*l = *(p++);*/
|
||||
DECODELENGTH(l, p);
|
||||
printf("%d - %.*s\n", i, l, p);
|
||||
p += l;
|
||||
/*l = *(p++);*/
|
||||
DECODELENGTH(l, p);
|
||||
printf(" %.*s\n", l, p);
|
||||
p += l;
|
||||
/*l = *(p++);*/
|
||||
DECODELENGTH(l, p);
|
||||
printf(" %.*s\n", l, p);
|
||||
p += l;
|
||||
}
|
||||
}
|
||||
|
||||
#define SENDCOMMAND(command, size) write(s, command, size); \
|
||||
printf("Command written type=%u\n", (unsigned)command[0]);
|
||||
|
||||
/* test program for minissdpd */
|
||||
int
|
||||
main(int argc, char * * argv)
|
||||
{
|
||||
char command1[] = "\x01\x00urn:schemas-upnp-org:device:InternetGatewayDevice";
|
||||
char command2[] = "\x02\x00uuid:fc4ec57e-b051-11db-88f8-0060085db3f6::upnp:rootdevice";
|
||||
char command3[] = { 0x03, 0x00 };
|
||||
struct sockaddr_un addr;
|
||||
int s;
|
||||
int i;
|
||||
unsigned char buf[2048];
|
||||
ssize_t n;
|
||||
const char * sockpath = "/var/run/minissdpd.sock";
|
||||
|
||||
for(i=0; i<argc-1; i++) {
|
||||
if(0==strcmp(argv[i], "-s"))
|
||||
sockpath = argv[++i];
|
||||
}
|
||||
command1[1] = sizeof(command1) - 3;
|
||||
command2[1] = sizeof(command2) - 3;
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
|
||||
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
|
||||
fprintf(stderr, "connecting to %s\n", addr.sun_path);
|
||||
perror("connect");
|
||||
return 1;
|
||||
}
|
||||
printf("Connected.\n");
|
||||
|
||||
SENDCOMMAND(command1, sizeof(command1) - 1);
|
||||
n = read(s, buf, sizeof(buf));
|
||||
printf("Response received %d bytes\n", (int)n);
|
||||
printresponse(buf, n);
|
||||
|
||||
SENDCOMMAND(command2, sizeof(command2) - 1);
|
||||
n = read(s, buf, sizeof(buf));
|
||||
printf("Response received %d bytes\n", (int)n);
|
||||
printresponse(buf, n);
|
||||
|
||||
SENDCOMMAND(command3, sizeof(command3));
|
||||
n = read(s, buf, sizeof(buf));
|
||||
printf("Response received %d bytes\n", (int)n);
|
||||
printresponse(buf, n);
|
||||
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* $Id: upnputils.c,v 1.3 2011/05/20 09:42:23 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2006-2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#ifdef AF_LINK
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
#include "upnputils.h"
|
||||
|
||||
int
|
||||
sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size)
|
||||
{
|
||||
char buffer[64];
|
||||
unsigned short port = 0;
|
||||
int n = -1;
|
||||
|
||||
switch(addr->sa_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
inet_ntop(addr->sa_family,
|
||||
&((struct sockaddr_in6 *)addr)->sin6_addr,
|
||||
buffer, sizeof(buffer));
|
||||
port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port);
|
||||
n = snprintf(str, size, "[%s]:%hu", buffer, port);
|
||||
break;
|
||||
case AF_INET:
|
||||
inet_ntop(addr->sa_family,
|
||||
&((struct sockaddr_in *)addr)->sin_addr,
|
||||
buffer, sizeof(buffer));
|
||||
port = ntohs(((struct sockaddr_in *)addr)->sin_port);
|
||||
n = snprintf(str, size, "%s:%hu", buffer, port);
|
||||
break;
|
||||
#ifdef AF_LINK
|
||||
case AF_LINK:
|
||||
{
|
||||
struct sockaddr_dl * sdl = (struct sockaddr_dl *)addr;
|
||||
n = snprintf(str, size, "index=%hu type=%d %s",
|
||||
sdl->sdl_index, sdl->sdl_type,
|
||||
link_ntoa(sdl));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
n = snprintf(str, size, "unknown address family %d", addr->sa_family);
|
||||
#if 0
|
||||
n = snprintf(str, size, "unknown address family %d "
|
||||
"%02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
addr->sa_family,
|
||||
addr->sa_data[0], addr->sa_data[1], (unsigned)addr->sa_data[2], addr->sa_data[3],
|
||||
addr->sa_data[4], addr->sa_data[5], (unsigned)addr->sa_data[6], addr->sa_data[7]);
|
||||
#endif
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/* $Id: upnputils.h,v 1.1 2011/05/15 08:58:41 nanard Exp $ */
|
||||
/* MiniUPnP project
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed
|
||||
* in the LICENCE file provided within the distribution */
|
||||
|
||||
#ifndef __UPNPUTILS_H__
|
||||
#define __UPNPUTILS_H__
|
||||
|
||||
/**
|
||||
* convert a struct sockaddr to a human readable string.
|
||||
* [ipv6]:port or ipv4:port
|
||||
* return the number of characters used (as snprintf)
|
||||
*/
|
||||
int
|
||||
sockaddr_to_string(const struct sockaddr * addr, char * str, size_t size);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue