C program – UDP Server to print UPNP Packets

This posts provides the C program with UDP server, which listens on UDP Multicast group 239.255.255.250 and port 1900 so that all the UPNP Packets flowing in the network can be captured for debugging during any application development.

$ vim upnp_udpserver.c 
/* 
 * udpserver.c - simple UDP server to print UPNP Packets
 * usage: udpserver <port>
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFSIZE 1024

/*
 * error - wrapper for perror
 */
void error(char *msg) {
  perror(msg);
  exit(1);
}

int main(int argc, char **argv) {
	int sockfd; /* socket */
	int portno; /* port to listen on */
	int clientlen; /* byte size of client's address */
	struct sockaddr_in serveraddr; /* server's addr */
	struct sockaddr_in clientaddr; /* client addr */
	struct hostent *hostp; /* client host info */
	char buf[BUFSIZE]; /* message buf */
	char *hostaddrp; /* dotted decimal host addr string */
	int optval; /* flag value for setsockopt */
	int n; /* message byte size */

	/* 
	* check command line arguments 
 	*/
	if (argc != 2) {
  		fprintf(stderr, "usage: %s <port>\n", argv[0]);
		exit(1);
	}
	portno = atoi(argv[1]);

	/* 
	* socket: create the parent socket 
	*/
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) 
		error("ERROR opening socket");

	optval = 1;
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));

	bzero((char *) &serveraddr, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr("239.255.255.250");
	serveraddr.sin_port = htons((unsigned short)portno);

	if (bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) 
		error("ERROR on binding");

	clientlen = sizeof(clientaddr);
	while (1) {

		/*
		* recvfrom: receive a UDP datagram from a client
		*/

		bzero(buf, BUFSIZE);
		n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *) &clientaddr, &clientlen);
		if (n < 0)
			error("ERROR in recvfrom");


		/* 
		* gethostbyaddr: determine who sent the datagram
		*/
		hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET);

		hostaddrp = inet_ntoa(clientaddr.sin_addr);
		if (hostaddrp == NULL)
			error("ERROR on inet_ntoa\n");
	
		if (hostp != NULL)	
			printf("server received %d/%d bytes: from %s (%s)\n %s\n", strlen(buf), n, hostp->h_name, hostaddrp, buf);
	}
	return 0;
}

Now, compile this program and run as,

$ gcc -o upnp_udpserver upnp_udpserver.c 
$ ./upnp_udpserver 1900 

Once you run the program as above, you will see the UPNP packets getting continuously captured like below,

server received 273/273 bytes: from _gateway (192.168.0.1)
 NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.0.1:1900/igd.xml
NT: uuid:565aa949-67c1-4c0e-aa8f-f349e6f59311
NTS: ssdp:alive
SERVER: ipos/7.0 UPnP/1.0 TL-WR740N/4.0
USN: uuid:565aa949-67c1-4c0e-aa8f-f349e6f59311


server received 328/328 bytes: from _gateway (192.168.0.1)
 NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.0.1:1900/igd.xml
NT: urn:schemas-wifialliance-org:device:WFADevice:1
NTS: ssdp:alive
SERVER: ipos/7.0 UPnP/1.0 TL-WR740N/4.0
USN: uuid:565aa949-67c1-4c0e-aa8f-f349e6f59311::urn:schemas-wifialliance-org:device:WFADevice:1


server received 338/338 bytes: from _gateway (192.168.0.1)
 NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.0.1:1900/igd.xml
NT: urn:schemas-wifialliance-org:service:WFAWLANConfig:1
NTS: ssdp:alive
SERVER: ipos/7.0 UPnP/1.0 TL-WR740N/4.0
USN: uuid:565aa949-67c1-4c0e-aa8f-f349e6f59311::urn:schemas-wifialliance-org:service:WFAWLANConfig:1

You can also refer to “Identify UPNP SSDP packets from your network”

Leave a Comment