1 /* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */
2 /* Project : miniupnp
3  * Author : Thomas Bernard
4  * Copyright (c) 2013-2015 Thomas Bernard
5  * This software is subject to the conditions detailed in the
6  * LICENCE file provided in this distribution. */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #ifdef _WIN32
12 #include <winsock2.h>
13 #endif /* _WIN32 */
14 #include "miniupnpc.h"
15 
16 struct upnp_dev_list {
17 	struct upnp_dev_list * next;
18 	char * descURL;
19 	struct UPNPDev * * array;
20 	size_t count;
21 	size_t allocated_count;
22 };
23 
24 #define ADD_DEVICE_COUNT_STEP 16
25 
add_device(struct upnp_dev_list ** list_head,struct UPNPDev * dev)26 void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev)
27 {
28 	struct upnp_dev_list * elt;
29 	size_t i;
30 
31 	if(dev == NULL)
32 		return;
33 	for(elt = *list_head; elt != NULL; elt = elt->next) {
34 		if(strcmp(elt->descURL, dev->descURL) == 0) {
35 			for(i = 0; i < elt->count; i++) {
36 				if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) {
37 					return;	/* already found */
38 				}
39 			}
40 			if(elt->count >= elt->allocated_count) {
41 				struct UPNPDev * * tmp;
42 				elt->allocated_count += ADD_DEVICE_COUNT_STEP;
43 				tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *));
44 				if(tmp == NULL) {
45 					fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *)));
46 					return;
47 				}
48 				elt->array = tmp;
49 			}
50 			elt->array[elt->count++] = dev;
51 			return;
52 		}
53 	}
54 	elt = malloc(sizeof(struct upnp_dev_list));
55 	if(elt == NULL) {
56 		fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list));
57 		return;
58 	}
59 	elt->next = *list_head;
60 	elt->descURL = strdup(dev->descURL);
61 	if(elt->descURL == NULL) {
62 		fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL);
63 		free(elt);
64 		return;
65 	}
66 	elt->allocated_count = ADD_DEVICE_COUNT_STEP;
67 	elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *));
68 	if(elt->array == NULL) {
69 		fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)));
70 		free(elt->descURL);
71 		free(elt);
72 		return;
73 	}
74 	elt->array[0] = dev;
75 	elt->count = 1;
76 	*list_head = elt;
77 }
78 
free_device(struct upnp_dev_list * elt)79 void free_device(struct upnp_dev_list * elt)
80 {
81 	free(elt->descURL);
82 	free(elt->array);
83 	free(elt);
84 }
85 
main(int argc,char ** argv)86 int main(int argc, char * * argv)
87 {
88 	const char * searched_device = NULL;
89 	const char * * searched_devices = NULL;
90 	const char * multicastif = 0;
91 	const char * minissdpdpath = 0;
92 	int ipv6 = 0;
93 	unsigned char ttl = 2;
94 	int error = 0;
95 	struct UPNPDev * devlist = 0;
96 	struct UPNPDev * dev;
97 	struct upnp_dev_list * sorted_list = NULL;
98 	struct upnp_dev_list * dev_array;
99 	int i;
100 
101 #ifdef _WIN32
102 	WSADATA wsaData;
103 	int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
104 	if(nResult != NO_ERROR)
105 	{
106 		fprintf(stderr, "WSAStartup() failed.\n");
107 		return -1;
108 	}
109 #endif
110 
111 	for(i = 1; i < argc; i++) {
112 		if(strcmp(argv[i], "-6") == 0)
113 			ipv6 = 1;
114 		else if(strcmp(argv[i], "-d") == 0) {
115 			if(++i >= argc) {
116 				fprintf(stderr, "%s option needs one argument\n", "-d");
117 				return 1;
118 			}
119 			searched_device = argv[i];
120 		} else if(strcmp(argv[i], "-t") == 0) {
121 			if(++i >= argc) {
122 				fprintf(stderr, "%s option needs one argument\n", "-t");
123 				return 1;
124 			}
125 			ttl = (unsigned char)atoi(argv[i]);
126 		} else if(strcmp(argv[i], "-l") == 0) {
127 			if(++i >= argc) {
128 				fprintf(stderr, "-l option needs at least one argument\n");
129 				return 1;
130 			}
131 			searched_devices = (const char * *)(argv + i);
132 			break;
133 		} else if(strcmp(argv[i], "-m") == 0) {
134 			if(++i >= argc) {
135 				fprintf(stderr, "-m option needs one argument\n");
136 				return 1;
137 			}
138 			multicastif = argv[i];
139 		} else {
140 			printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]);
141 			printf("options :\n");
142 			printf("   -6 : use IPv6\n");
143 			printf("   -m address/ifname : network interface to use for multicast\n");
144 			printf("   -d <device string> : search only for this type of device\n");
145 			printf("   -l <device1> <device2> ... : search only for theses types of device\n");
146 			printf("   -t ttl : set multicast TTL. Default value is 2.\n");
147 			printf("   -h : this help\n");
148 			return 1;
149 		}
150 	}
151 
152 	if(searched_device) {
153 		printf("searching UPnP device type %s\n", searched_device);
154 		devlist = upnpDiscoverDevice(searched_device,
155 		                             2000, multicastif, minissdpdpath,
156 		                             0/*localport*/, ipv6, ttl, &error);
157 	} else if(searched_devices) {
158 		printf("searching UPnP device types :\n");
159 		for(i = 0; searched_devices[i]; i++)
160 			printf("\t%s\n", searched_devices[i]);
161 		devlist = upnpDiscoverDevices(searched_devices,
162 		                              2000, multicastif, minissdpdpath,
163 		                              0/*localport*/, ipv6, ttl, &error, 1);
164 	} else {
165 		printf("searching all UPnP devices\n");
166 		devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath,
167 		                             0/*localport*/, ipv6, ttl, &error);
168 	}
169 	if(devlist) {
170 		for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) {
171 			printf("%3d: %-48s\n", i, dev->st);
172 			printf("     %s\n", dev->descURL);
173 			printf("     %s\n", dev->usn);
174 			add_device(&sorted_list, dev);
175 		}
176 		putchar('\n');
177 		for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) {
178 			printf("%s :\n", dev_array->descURL);
179 			for(i = 0; (unsigned)i < dev_array->count; i++) {
180 				printf("%2d: %s\n", i+1, dev_array->array[i]->st);
181 				printf("    %s\n", dev_array->array[i]->usn);
182 			}
183 			putchar('\n');
184 		}
185 		freeUPNPDevlist(devlist);
186 		while(sorted_list != NULL) {
187 			dev_array = sorted_list;
188 			sorted_list = sorted_list->next;
189 			free_device(dev_array);
190 		}
191 	} else {
192 		printf("no device found.\n");
193 	}
194 
195 	return 0;
196 }
197 
198