├── CHANGES.TXT ├── CREDITS.TXT ├── GNUmakefile ├── LICENSE.TXT ├── Makefile ├── README.TXT ├── README.md └── tools ├── iot-scan.c ├── iot-scan.c~ ├── iot-scan.h ├── iot-scan.h~ ├── iot-tddp.c ├── iot-tddp.c~ ├── iot-tddp.h ├── iot-tddp.h~ ├── iot-tl-plug.c ├── iot-tl-plug.h ├── iot-toolkit.h ├── libiot.c ├── libiot.h └── libiot.h~ /CHANGES.TXT: -------------------------------------------------------------------------------- 1 | SI6 Networks IoT Toolkit v1.0 (Jan) 2 | * Initial release during Troopers 2017 (www.troopers.de) 3 | 4 | -------------------------------------------------------------------------------- /CREDITS.TXT: -------------------------------------------------------------------------------- 1 | CREDITS 2 | ------- 3 | 4 | ** Contributors ** 5 | 6 | The following people sent patches that were incorporated into this release 7 | of the toolkit: 8 | 9 | [None] 10 | 11 | 12 | ** Package maintainers ** 13 | 14 | Availability of packages for different operating systems makes it easier for 15 | users to install and update the toolkit, and for the toolkit to integrate 16 | better with the operating systems. 17 | 18 | These are the maintainers for each of the different packages: 19 | 20 | [TBD] 21 | 22 | ** Troubleshooting/Debugging ** 23 | 24 | Spotting bugs in networking tools can be tricky, since at times they only show 25 | up in specific network scenarios. 26 | 27 | The following indviduals provided great help in identifying bugs in the 28 | toolkit (thus leading to fixes and improvements): 29 | 30 | [None] 31 | 32 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # 2 | # SI6 Networks' IoT Toolkit Makefile (for GNU make) 3 | # 4 | # Notes to package developers: 5 | # 6 | # By default, binaries will be installed in /usr/local/bin, manual pages in 7 | # /usr/local/man, data files in /usr/local/share/iot-toolkit, and configuration 8 | # files in /etc 9 | # 10 | # The path of the binaries and data files can be overriden by setting "PREFIX" 11 | # variable accordingly. The path of the manual pages can be overriden by setting 12 | # the MANPREFIX variable. Typically, packages will set these variables as follows: 13 | # 14 | # PREFIX=/usr/ 15 | # MANPREFIX=/usr/share 16 | # 17 | # Finally, please note that this makefile supports the DESTDIR variable, as 18 | # typically employed by package developers. 19 | 20 | 21 | # XXX: Remove prior to release 22 | # XXX: check which tools should go into BINTOOL or SBINTOOLS 23 | 24 | CC= clang 25 | CFLAGS+= -Wall 26 | LDFLAGS+= -lpcap -lm 27 | LDFLAGS_SSL= -lcrypto 28 | 29 | 30 | ifeq ($(shell uname),SunOS) 31 | LDFLAGS+=-lsocket -lnsl 32 | OS=SunOS 33 | endif 34 | 35 | 36 | ifndef PREFIX 37 | PREFIX=/usr/local 38 | ifndef MANPREFIX 39 | MANPREFIX=/usr/local 40 | endif 41 | else 42 | ifndef MANPREFIX 43 | MANPREFIX=/usr/share 44 | endif 45 | endif 46 | 47 | 48 | ETCPATH= $(DESTDIR)/etc 49 | MANPATH= $(DESTDIR)$(MANPREFIX)/man 50 | DATAPATH= $(DESTDIR)$(PREFIX)/share/iot-toolkit 51 | BINPATH= $(DESTDIR)$(PREFIX)/bin 52 | SBINPATH= $(DESTDIR)$(PREFIX)/sbin 53 | SRCPATH= tools 54 | 55 | 56 | SBINTOOLS= iot-scan iot-tl-plug 57 | BINTOOLS= iot-tddp 58 | TOOLS= $(BINTOOLS) $(SBINTOOLS) 59 | LIBS= libiot.o 60 | 61 | all: $(TOOLS) # data/iot-toolkit.conf 62 | 63 | iot-scan: $(SRCPATH)/iot-scan.c $(SRCPATH)/iot-scan.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 64 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-scan $(SRCPATH)/iot-scan.c $(LIBS) $(LDFLAGS) 65 | 66 | iot-tl-plug: $(SRCPATH)/iot-tl-plug.c $(SRCPATH)/iot-tl-plug.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 67 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-tl-plug $(SRCPATH)/iot-tl-plug.c $(LIBS) $(LDFLAGS) 68 | 69 | iot-tddp: $(SRCPATH)/iot-tddp.c $(SRCPATH)/iot-tddp.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 70 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-tddp $(SRCPATH)/iot-tddp.c $(LIBS) $(LDFLAGS) $(LDFLAGS_SSL) 71 | 72 | libiot.o: $(SRCPATH)/libiot.c $(SRCPATH)/libiot.h 73 | $(CC) $(CPPFLAGS) $(CFLAGS) -c -o libiot.o $(SRCPATH)/libiot.c 74 | 75 | data/iot-toolkit.conf: 76 | echo "# SI6 Networks' IoT Toolkit Configuration File" > \ 77 | data/iot-toolkit.conf 78 | 79 | clean: 80 | rm -f $(TOOLS) $(LIBS) 81 | # rm -f data/iot-toolkit.conf 82 | 83 | install: all 84 | ifneq ($(OS),SunOS) 85 | # Install the binaries 86 | install -m0755 -d $(BINPATH) 87 | install -m0755 -d $(SBINPATH) 88 | install -m0755 $(BINTOOLS) $(BINPATH) 89 | install -m0755 $(SBINTOOLS) $(SBINPATH) 90 | 91 | # Install the configuration file 92 | # install -m0755 -d $(ETCPATH) 93 | # install -m0644 data/iot-toolkit.conf $(ETCPATH) 94 | 95 | # Install the manual pages 96 | # install -m0755 -d $(MANPATH)/man1 97 | # install -m0644 manuals/*.1 $(MANPATH)/man1 98 | # install -m0755 -d $(MANPATH)/man5 99 | # install -m0644 manuals/*.5 $(MANPATH)/man5 100 | # install -m0755 -d $(MANPATH)/man7 101 | # install -m0644 manuals/*.7 $(MANPATH)/man7 102 | else 103 | # Install the binaries 104 | install -m 0755 -d $(BINPATH) 105 | install -m 0755 -d $(SBINPATH) 106 | 107 | install -m 0755 -f $(SBINPATH) iot-scan 108 | install -m 0755 -f $(SBINPATH) iot-tl-plug 109 | 110 | # Install the configuration file 111 | # install -m 0755 -d $(ETCPATH) 112 | # install -m 0644 -f $(ETCPATH) data/iot-toolkit.conf 113 | 114 | # Install the manual pages 115 | # install -m 0755 -d $(MANPATH)/man1 116 | # install -m 0644 -f $(MANPATH)/man1 manuals/iot-scan.1 117 | # install -m 0644 -f $(MANPATH)/man1 manuals/iot-tl-plug.1 118 | # install -m 0755 -d $(MANPATH)/man5 119 | # install -m 0644 -f $(MANPATH)/man5 manuals/iot-toolkit.conf.5 120 | # install -m 0755 -d $(MANPATH)/man7 121 | # install -m 0644 -f $(MANPATH)/man7 manuals/iot-toolkit.7 122 | endif 123 | 124 | 125 | uninstall: 126 | # Remove the binaries 127 | rm -f $(SBINPATH)/iot-scan 128 | rm -f $(SBINPATH)/iot-tl-plug 129 | 130 | # Remove the configuration file 131 | # rm -f $(ETCPATH)/iot-toolkit.conf 132 | 133 | # Remove the manual pages 134 | # rm -f $(MANPATH)/man1/iot-scan.1 135 | # rm -f $(MANPATH)/man1/iot-tl-plug.1 136 | # rm -f $(MANPATH)/man5/iot-toolkit.conf.5 137 | # rm -f $(MANPATH)/man7/iot-toolkit.7 138 | 139 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # SI6 Networks' IoT Toolkit Makefile 3 | # 4 | # Notes to package developers: 5 | # 6 | # By default, binaries will be installed in /usr/local/bin, manual pages in 7 | # /usr/local/man, data files in /usr/local/share/iot-toolkit, and configuration 8 | # files in /etc 9 | # 10 | # The path of the binaries and data files can be overriden by setting "PREFIX" 11 | # variable accordingly. The path of the manual pages can be overriden by setting 12 | # the MANPREFIX variable. Typically, packages will set these variables as follows: 13 | # 14 | # PREFIX=/usr 15 | # MANPREFIX=/usr/share 16 | # 17 | # Finally, please note that this makefile supports the DESTDIR variable, as 18 | # typically employed by package developers. 19 | 20 | 21 | CC?=clang 22 | CFLAGS+= -Wall 23 | LDFLAGS+= -lpcap -lm 24 | LDFLAGS_SSL= -lcrypto 25 | 26 | .ifndef(PREFIX) 27 | PREFIX=/usr/local 28 | .ifndef(MANPREFIX) 29 | MANPREFIX=/usr/local 30 | .endif 31 | .else 32 | .ifndef(MANPREFIX) 33 | MANPREFIX=/usr/share 34 | .endif 35 | .endif 36 | 37 | ETCPATH= $(DESTDIR)/etc 38 | MANPATH= $(DESTDIR)$(MANPREFIX)/man 39 | DATAPATH= $(DESTDIR)$(PREFIX)/share/iot-toolkit 40 | BINPATH= $(DESTDIR)$(PREFIX)/bin 41 | SBINPATH= $(DESTDIR)$(PREFIX)/sbin 42 | SRCPATH= tools 43 | 44 | 45 | SBINTOOLS= iot-scan iot-tl-plug 46 | BINTOOLS= iot-tddp 47 | TOOLS= $(BINTOOLS) $(SBINTOOLS) 48 | LIBS= libiot.o 49 | 50 | all: $(TOOLS) data/iot-toolkit.conf 51 | 52 | iot-scan: $(SRCPATH)/iot-scan.c $(SRCPATH)/iot-scan.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 53 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-scan $(SRCPATH)/iot-scan.c $(LIBS) $(LDFLAGS) 54 | 55 | iot-tl-plug: $(SRCPATH)/iot-tl-plug.c $(SRCPATH)/iot-tl-plug.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 56 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-tl-plug $(SRCPATH)/iot-tl-plug.c $(LIBS) $(LDFLAGS) 57 | 58 | iot-tddp: $(SRCPATH)/iot-tddp.c $(SRCPATH)/iot-tddp.h $(SRCPATH)/iot-toolkit.h $(LIBS) $(SRCPATH)/libiot.h 59 | $(CC) $(CPPFLAGS) $(CFLAGS) -o iot-tddp $(SRCPATH)/iot-tddp.c $(LIBS) $(LDFLAGS) $(LDFLAGS_SSL) 60 | 61 | libiot.o: $(SRCPATH)/libiot.c $(SRCPATH)/libiot.h 62 | $(CC) $(CPPFLAGS) $(CFLAGS) -c -o libiot.o $(SRCPATH)/libiot.c 63 | 64 | data/iot-toolkit.conf: 65 | echo "# SI6 Networks' IoT Toolkit Configuration File" > \ 66 | data/iot-toolkit.conf 67 | 68 | clean: 69 | rm -f $(TOOLS) $(LIBS) 70 | rm -f data/iot-toolkit.conf 71 | 72 | install: all 73 | # Install the binaries 74 | install -m0755 -d $(BINPATH) 75 | install -m0755 -d $(SBINPATH) 76 | install -m0755 $(BINTOOLS) $(BINPATH) 77 | install -m0755 $(SBINTOOLS) $(SBINPATH) 78 | 79 | # Install the configuration file 80 | install -m0755 -d $(ETCPATH) 81 | install -m0644 data/iot-toolkit.conf $(ETCPATH) 82 | 83 | # Install the manual pages 84 | install -m0755 -d $(MANPATH)/man1 85 | install -m0644 manuals/*.1 $(MANPATH)/man1 86 | install -m0755 -d $(MANPATH)/man5 87 | install -m0644 manuals/*.5 $(MANPATH)/man5 88 | install -m0755 -d $(MANPATH)/man7 89 | install -m0644 manuals/*.7 $(MANPATH)/man7 90 | 91 | uninstall: 92 | # Remove the binaries 93 | rm -f $(BINPATH)/iot-tddp 94 | rm -f $(SBINPATH)/iot-scan 95 | rm -f $(SBINPATH)/iot-tl-plug 96 | 97 | # Remove the configuration file 98 | rm -f $(ETCPATH)/iot-toolkit.conf 99 | 100 | # Remove the manual pages 101 | rm -f $(MANPATH)/man1/iot-scan.1 102 | rm -f $(MANPATH)/man1/iot-tl-plug.1 103 | rm -f $(MANPATH)/man1/iot-tddp.1 104 | rm -f $(MANPATH)/man5/iot-toolkit.conf.5 105 | rm -f $(MANPATH)/man7/iot-toolkit.7 106 | 107 | -------------------------------------------------------------------------------- /README.TXT: -------------------------------------------------------------------------------- 1 | ******************************************************************************* 2 | * SI6 Networks IoT Toolkit v1.0 ( ) * 3 | ******************************************************************************* 4 | 5 | Description of each of the files and directories: 6 | ------------------------------------------------- 7 | 8 | data: Contains the configuration files and miscellaneous databases. 9 | manuals: Contains the manual pages for the security assessment tools. 10 | tools: Contains the source code for the security assessment tools. 11 | CHANGES.TXT: Contains the changelog of the toolkit 12 | CREDITS.TXT: Contains the credits of this project. 13 | LICENSE.TXT: Contains the license for this software (GPLv3) 14 | README.TXT: This file. 15 | 16 | 17 | Building the tools 18 | ------------------ 19 | 20 | You can build the tools by running the following command: 21 | 22 | make all 23 | 24 | You can install the tools, configuration file, database, and existing manual 25 | pages by running the following command: 26 | 27 | make install 28 | 29 | Note: The libpcap and the libssl libraries must be previously installed on 30 | the system. The corresponding packages are typically named "libpcap-dev" and 31 | libssl-dev, respctively. 32 | 33 | All the tools have been tested to build (both with gcc and clang) and run on 34 | Debian GNU/Linux 7.0 and FreeBSD 9.0. 35 | 36 | 37 | Bug reports 38 | ----------- 39 | 40 | Please send any bug reports to Fernando Gont 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iot-toolkit 2 | SI6 Networks' IoT Toolkit 3 | -------------------------------------------------------------------------------- /tools/iot-scan.c~: -------------------------------------------------------------------------------- 1 | /* 2 | * iot-scan: An IoT Scanning Tool 3 | * 4 | * Copyright (C) 2017 Fernando Gont 5 | * 6 | * Programmed by Fernando Gont for SI6 Networks 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * Build with: make iot-scan 22 | * 23 | * It requires that the libpcap library be installed on your system. 24 | * 25 | * Please send any bug reports to Fernando Gont 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #include "iot-scan.h" 54 | #include "iot-toolkit.h" 55 | #include "libiot.h" 56 | 57 | /* #define DEBUG */ 58 | 59 | /* Function prototypes */ 60 | void init_packet_data(struct iface_data *); 61 | void free_host_entries(struct host_list *); 62 | int host_scan_local(pcap_t *, struct iface_data *, struct in6_addr *, unsigned char, \ 63 | struct host_entry *); 64 | void print_help(void); 65 | int print_host_entries(struct host_list *, unsigned char); 66 | void local_sig_alarm(int); 67 | void usage(void); 68 | int process_config_file(const char *); 69 | 70 | /* Used for multiscan */ 71 | struct host_list host_local, host_global, host_candidate; 72 | struct host_entry *host_locals[MAX_IPV6_ENTRIES], *host_globals[MAX_IPV6_ENTRIES]; 73 | struct host_entry *host_candidates[MAX_IPV6_ENTRIES]; 74 | 75 | /* Used for router discovery */ 76 | struct iface_data idata; 77 | 78 | /* Variables used for learning the default router */ 79 | struct ether_addr router_ether, rs_ether; 80 | struct in6_addr router_ipv6, rs_ipv6; 81 | 82 | struct in6_addr randprefix; 83 | unsigned char randpreflen; 84 | 85 | bpf_u_int32 my_netmask; 86 | bpf_u_int32 my_ip; 87 | struct bpf_program pcap_filter; 88 | char dev[64], errbuf[PCAP_ERRBUF_SIZE]; 89 | unsigned char buffer[BUFFER_SIZE], buffrh[MIN_IPV6_HLEN + MIN_TCP_HLEN]; 90 | char readbuff[BUFFER_SIZE], sendbuff[BUFFER_SIZE]; 91 | ssize_t nreadbuff, nsendbuff; 92 | char line[LINE_BUFFER_SIZE]; 93 | unsigned char *v6buffer, *ptr, *startofprefixes; 94 | char *pref; 95 | 96 | struct ether_header *ethernet; 97 | unsigned int ndst=0; 98 | 99 | char *lasts, *rpref; 100 | char *charptr; 101 | 102 | size_t nw; 103 | unsigned long ul_res, ul_val; 104 | unsigned int i, j, startrand; 105 | unsigned int skip; 106 | unsigned char dstpreflen; 107 | 108 | uint16_t mask; 109 | 110 | char plinkaddr[ETHER_ADDR_PLEN], pv4addr[INET_ADDRSTRLEN]; 111 | char pv6addr[INET6_ADDRSTRLEN]; 112 | unsigned char verbose_f=FALSE; 113 | unsigned char dstaddr_f=FALSE, timestamps_f=FALSE, scan_local_f=FALSE; 114 | 115 | 116 | 117 | unsigned char dst_f=FALSE, end_f=FALSE, endpscan_f=FALSE; 118 | unsigned char donesending_f=FALSE; 119 | uint16_t srcport, dstport; 120 | uint32_t scan_type; 121 | char scan_type_f=FALSE; 122 | unsigned long pktinterval, rate; 123 | unsigned int packetsize; 124 | 125 | struct prefixv4_entry prefix; 126 | 127 | char *charstart, *charend, *lastcolon; 128 | unsigned int nsleep; 129 | int sel; 130 | fd_set sset, rset, wset, eset; 131 | struct timeval curtime, pcurtime, lastprobe; 132 | struct tm pcurtimetm; 133 | unsigned int retrans=0; 134 | char TP_LINK_SMART_DISCOVER[]="{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}"; 135 | char TP_LINK_IP_CAMERA_DISCOVER[]={0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x17, 0x00, \ 136 | 0x07, 0xd8, 0xa1, 0x4f, 0xc2, 0x90, 0x98, 0x93, 0xec, 0x5b, 0x80, 0x5e, \ 137 | 0xfa, 0xe2, 0x06, 0xd5, 0x63, 0x86, 0xb6, 0xdc, 0x3c, 0x8a, 0xff, 0x48, \ 138 | 0xce, 0x6c, 0xbd, 0x97, 0xb7, 0x1c, 0x21, 0xe9, 0xbd, 0x59, 0x30, 0xd7, \ 139 | 0x19, 0xd1, 0x22, 0x77, 0x6b, 0xd9, 0x43, 0x19, 0xd8, 0x87, 0x9f, 0xbb}; 140 | 141 | char TP_LINK_IP_CAMERA_RESPONSE[]= {0x02, 0x03, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 142 | 0x17, 0x00, 0x72, 0xa9, 0xa2, 0x32, 0xad, 0xd8, 0x65, 0xae, \ 143 | 0x78, 0x40, 0xad, 0x62, 0x08, 0xf9, 0x34, 0x16}; 144 | 145 | int main(int argc, char **argv){ 146 | extern char *optarg; 147 | int r; 148 | struct addrinfo hints, *res, *aiptr; 149 | struct target_ipv6 target; 150 | struct timeval timeout; 151 | void *voidptr; 152 | const int on=1; 153 | struct sockaddr_in sockaddr_in, sockaddr_from, sockaddr_to; 154 | socklen_t sockaddrfrom_len; 155 | struct json *json1, *json2, *json3; 156 | struct json_value json_value; 157 | char *alias, *dev_name, *type, *model; 158 | 159 | static struct option longopts[] = { 160 | {"interface", required_argument, 0, 'i'}, 161 | {"dst-address", required_argument, 0, 'd'}, 162 | {"local-scan", no_argument, 0, 'L'}, 163 | {"retrans", required_argument, 0, 'x'}, 164 | {"timeout", required_argument, 0, 'O'}, 165 | {"verbose", no_argument, 0, 'v'}, 166 | {"help", no_argument, 0, 'h'}, 167 | {0, 0, 0, 0 } 168 | }; 169 | 170 | char shortopts[]= "i:d:Lx:O:vh"; 171 | 172 | char option; 173 | 174 | if(argc<=1){ 175 | usage(); 176 | exit(EXIT_FAILURE); 177 | } 178 | 179 | srandom(time(NULL)); 180 | 181 | init_iface_data(&idata); 182 | 183 | 184 | while((r=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 185 | option= r; 186 | 187 | switch(option) { 188 | case 'i': /* Interface */ 189 | strncpy(idata.iface, optarg, IFACE_LENGTH-1); 190 | idata.iface[IFACE_LENGTH-1]=0; 191 | idata.ifindex= if_nametoindex(idata.iface); 192 | idata.iface_f=TRUE; 193 | break; 194 | 195 | case 'd': /* IPv6 Destination Address/Prefix */ 196 | /* The '-d' option contains a domain name */ 197 | if((charptr = strtok_r(optarg, "/", &lasts)) == NULL){ 198 | puts("Error in Destination Address"); 199 | exit(EXIT_FAILURE); 200 | } 201 | 202 | strncpy(target.name, charptr, NI_MAXHOST); 203 | target.name[NI_MAXHOST-1]=0; 204 | 205 | if((charptr = strtok_r(NULL, " ", &lasts)) != NULL){ 206 | prefix.len = atoi(charptr); 207 | 208 | if(prefix.len > 32){ 209 | puts("Prefix length error in IP Destination Address"); 210 | exit(EXIT_FAILURE); 211 | } 212 | } 213 | else{ 214 | prefix.len= 32; 215 | } 216 | 217 | memset(&hints, 0, sizeof(hints)); 218 | hints.ai_family= AF_INET; 219 | hints.ai_canonname = NULL; 220 | hints.ai_addr = NULL; 221 | hints.ai_next = NULL; 222 | hints.ai_socktype= SOCK_DGRAM; 223 | 224 | if( (target.res = getaddrinfo(target.name, NULL, &hints, &res)) != 0){ 225 | printf("Unknown Destination '%s': %s\n", target.name, gai_strerror(target.res)); 226 | exit(1); 227 | } 228 | 229 | for(aiptr=res; aiptr != NULL; aiptr=aiptr->ai_next){ 230 | if(aiptr->ai_family != AF_INET) 231 | continue; 232 | 233 | if(aiptr->ai_addrlen != sizeof(struct sockaddr_in)) 234 | continue; 235 | 236 | if(aiptr->ai_addr == NULL) 237 | continue; 238 | 239 | prefix.ip= ( (struct sockaddr_in *)aiptr->ai_addr)->sin_addr; 240 | } 241 | 242 | freeaddrinfo(res); 243 | 244 | idata.dstaddr= prefix.ip; 245 | idata.dstaddr_f= TRUE; 246 | dst_f=TRUE; 247 | break; 248 | 249 | case 'L': 250 | scan_local_f=TRUE; 251 | break; 252 | 253 | case 'x': 254 | idata.local_retrans=atoi(optarg); 255 | break; 256 | 257 | case 'O': 258 | idata.local_timeout=atoi(optarg); 259 | break; 260 | 261 | case 'v': /* Be verbose */ 262 | idata.verbose_f++; 263 | break; 264 | 265 | case 'h': /* Help */ 266 | print_help(); 267 | exit(EXIT_FAILURE); 268 | break; 269 | 270 | default: 271 | usage(); 272 | exit(EXIT_FAILURE); 273 | break; 274 | 275 | } /* switch */ 276 | } /* while(getopt) */ 277 | 278 | /* 279 | XXX: This is rather ugly, but some local functions need to check for verbosity, and it was not warranted 280 | to pass &idata as an argument 281 | */ 282 | verbose_f= idata.verbose_f; 283 | 284 | if(geteuid()){ 285 | puts("iot-scan needs superuser privileges to run"); 286 | exit(EXIT_FAILURE); 287 | } 288 | 289 | if(scan_local_f && !idata.iface_f){ 290 | /* XXX This should later allow to just specify local scan and automatically choose an interface */ 291 | puts("Must specify the network interface with the -i option when a local scan is selected"); 292 | /* exit(EXIT_FAILURE); */ 293 | } 294 | 295 | if(!dst_f && !scan_local_f){ 296 | if(idata.verbose_f) 297 | puts("Must specify either a destination prefix ('-d'), or a local scan ('-L')"); 298 | 299 | exit(EXIT_FAILURE); 300 | } 301 | 302 | release_privileges(); 303 | 304 | if(get_local_addrs(&idata) == FAILURE){ 305 | puts("Error obtaining list of local interfaces and addresses"); 306 | exit(EXIT_FAILURE); 307 | } 308 | 309 | /* debug_print_iflist(&(idata.iflist)); */ 310 | 311 | if(!scan_type_f){ 312 | scan_type= IP_CAMERAS | SMART_PLUGS; 313 | } 314 | 315 | if(scan_local_f){ 316 | host_local.nhosts=0; 317 | host_local.maxhosts= MAX_IPV6_ENTRIES; 318 | host_local.host= host_locals; 319 | 320 | /* If an interface was specified, we select an IPv4 address from such interface */ 321 | if(idata.iface_f){ 322 | if( (voidptr=find_v4addr_for_iface(&(idata.iflist), idata.iface)) == NULL){ 323 | printf("No IPv4 address for interface %s\n", idata.iface); 324 | exit(EXIT_FAILURE); 325 | } 326 | 327 | idata.srcaddr= *((struct in_addr *) voidptr); 328 | } 329 | else{ 330 | if( (voidptr=find_v4addr(&(idata.iflist))) == NULL){ 331 | puts("No IPv4 address available on local host"); 332 | exit(EXIT_FAILURE); 333 | } 334 | 335 | idata.srcaddr= *((struct in_addr *)voidptr); 336 | } 337 | 338 | if( (idata.fd=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 339 | puts("Could not create socket"); 340 | exit(EXIT_FAILURE); 341 | } 342 | 343 | if( setsockopt(idata.fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1){ 344 | puts("Error while setting SO_BROADCAST socket option"); 345 | exit(EXIT_FAILURE); 346 | } 347 | 348 | memset(&sockaddr_in, 0, sizeof(sockaddr_in)); 349 | sockaddr_in.sin_family= AF_INET; 350 | sockaddr_in.sin_port= 0; /* Allow Sockets API to set an ephemeral port */ 351 | sockaddr_in.sin_addr= idata.srcaddr; 352 | 353 | if(bind(idata.fd, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1){ 354 | puts("Error bind()ing socket to local address"); 355 | exit(EXIT_FAILURE); 356 | } 357 | 358 | if(scan_type | SMART_PLUGS){ 359 | memset(&sockaddr_to, 0, sizeof(sockaddr_to)); 360 | sockaddr_to.sin_family= AF_INET; 361 | sockaddr_to.sin_port= htons(TP_LINK_SMART_PORT); 362 | 363 | memset(&sockaddr_from, 0, sizeof(sockaddr_from)); 364 | sockaddr_from.sin_family= AF_INET; 365 | sockaddrfrom_len=sizeof(sockaddr_from); 366 | 367 | 368 | if ( inet_pton(AF_INET, IP_LIMITED_MULTICAST, &(sockaddr_to.sin_addr)) <= 0){ 369 | puts("inet_pton(): Error setting multicast address"); 370 | exit(EXIT_FAILURE); 371 | } 372 | 373 | FD_ZERO(&sset); 374 | FD_SET(idata.fd, &sset); 375 | 376 | lastprobe.tv_sec= 0; 377 | lastprobe.tv_usec=0; 378 | idata.pending_write_f=TRUE; 379 | 380 | /* The end_f flag is set after the last probe has been sent and a timeout period has elapsed. 381 | That is, we give responses enough time to come back 382 | */ 383 | while(!end_f){ 384 | rset= sset; 385 | wset= sset; 386 | eset= sset; 387 | 388 | if(!donesending_f){ 389 | /* This is the retransmission timer */ 390 | timeout.tv_sec= 1; 391 | timeout.tv_usec= 0; 392 | } 393 | else{ 394 | /* XXX: This should use the parameter from command line */ 395 | timeout.tv_sec= idata.local_timeout; 396 | timeout.tv_usec=0; 397 | } 398 | 399 | /* 400 | Check for readability and exceptions. We only check for writeability if there is pending data 401 | to send. 402 | */ 403 | if((sel=select(idata.fd+1, &rset, (idata.pending_write_f?&wset:NULL), &eset, &timeout)) == -1){ 404 | if(errno == EINTR){ 405 | continue; 406 | } 407 | else{ 408 | perror("iot-scan:"); 409 | exit(EXIT_FAILURE); 410 | } 411 | } 412 | 413 | if(gettimeofday(&curtime, NULL) == -1){ 414 | if(idata.verbose_f) 415 | perror("iot-scan"); 416 | 417 | exit(EXIT_FAILURE); 418 | } 419 | 420 | /* Check whether we have finished probing all targets */ 421 | if(donesending_f){ 422 | /* 423 | Just wait for SELECT_TIMEOUT seconds for any incoming responses. 424 | */ 425 | 426 | if(is_time_elapsed(&curtime, &lastprobe, idata.local_timeout * 1000000)){ 427 | end_f=TRUE; 428 | } 429 | } 430 | 431 | 432 | if(sel && FD_ISSET(idata.fd, &rset)){ 433 | /* XXX: Process response packet */ 434 | 435 | if( (nreadbuff = recvfrom(idata.fd, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 436 | perror("iot-scan: "); 437 | exit(EXIT_FAILURE); 438 | } 439 | 440 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 441 | perror("iot-scan: "); 442 | exit(EXIT_FAILURE); 443 | } 444 | 445 | tp_link_decrypt((unsigned char *)readbuff, nreadbuff); 446 | 447 | alias= NULL_STRING; 448 | dev_name= NULL_STRING; 449 | type= NULL_STRING; 450 | model= NULL_STRING; 451 | 452 | /* Get to system:get_sysinfo */ 453 | if( (json1=json_get_objects(readbuff, (nreadbuff))) != NULL){ 454 | if( json_get_value(json1, &json_value, "\"system\"")){ 455 | if( (json2=json_get_objects(json_value.value, json_value.len)) != NULL){ 456 | if( json_get_value(json2, &json_value, "\"get_sysinfo\"")){ 457 | if( (json3=json_get_objects(json_value.value, json_value.len)) != NULL){ 458 | json_remove_quotes(json3); 459 | if( json_get_value(json3, &json_value, "type")){ 460 | type=json_value.value; 461 | } 462 | if( json_get_value(json3, &json_value, "model")){ 463 | model=json_value.value; 464 | } 465 | if( json_get_value(json3, &json_value, "dev_name")){ 466 | dev_name=json_value.value; 467 | } 468 | if( json_get_value(json3, &json_value, "alias")){ 469 | alias=json_value.value; 470 | } 471 | /* 472 | printf("%s: \"%s\" (\"%s\": %s %s)\n", pv4addr, alias, dev_name, type, model); 473 | */ 474 | printf("%s # %s: TP-Link %s: %s: \"%s\"\n", pv4addr, type, model, dev_name, alias); 475 | 476 | } 477 | } 478 | } 479 | } 480 | } 481 | 482 | } 483 | 484 | 485 | if(!donesending_f && !idata.pending_write_f && is_time_elapsed(&curtime, &lastprobe, 1 * 1000000)){ 486 | idata.pending_write_f=TRUE; 487 | continue; 488 | } 489 | 490 | if(!donesending_f && idata.pending_write_f && FD_ISSET(idata.fd, &wset)){ 491 | idata.pending_write_f=FALSE; 492 | 493 | /* XXX: SEND PROBE PACKET */ 494 | nsendbuff= Strnlen(TP_LINK_SMART_DISCOVER, MAX_TP_COMMAND_LENGTH); 495 | memcpy(sendbuff, TP_LINK_SMART_DISCOVER, nsendbuff); 496 | tp_link_crypt((unsigned char *)sendbuff, nsendbuff); 497 | /* 498 | if( sendto(idata.fd, encrypted, sizeof(encrypted), 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 499 | perror("iot-scan: "); 500 | exit(EXIT_FAILURE); 501 | } 502 | */ 503 | 504 | if( sendto(idata.fd, sendbuff, nsendbuff, 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 505 | perror("iot-scan: "); 506 | exit(EXIT_FAILURE); 507 | } 508 | 509 | if(gettimeofday(&lastprobe, NULL) == -1){ 510 | if(idata.verbose_f) 511 | perror("iot-scan"); 512 | 513 | exit(EXIT_FAILURE); 514 | } 515 | 516 | retrans++; 517 | 518 | if(retrans >= idata.local_retrans) 519 | donesending_f= 1; 520 | 521 | } 522 | 523 | 524 | if(FD_ISSET(idata.fd, &eset)){ 525 | if(idata.verbose_f) 526 | puts("iot-scaner: Found exception on descriptor"); 527 | 528 | exit(EXIT_FAILURE); 529 | } 530 | } 531 | 532 | } 533 | if(scan_type | IP_CAMERAS){ 534 | /* puts("Voy a escanear camaras"); */ 535 | donesending_f=FALSE; 536 | end_f=FALSE; 537 | memset(&sockaddr_to, 0, sizeof(sockaddr_to)); 538 | sockaddr_to.sin_family= AF_INET; 539 | sockaddr_to.sin_port= htons(TP_LINK_IP_CAMERA_TDDP_PORT); 540 | 541 | memset(&sockaddr_from, 0, sizeof(sockaddr_from)); 542 | sockaddr_from.sin_family= AF_INET; 543 | sockaddrfrom_len=sizeof(sockaddr_from); 544 | 545 | 546 | if ( inet_pton(AF_INET, IP_LIMITED_MULTICAST, &(sockaddr_to.sin_addr)) <= 0){ 547 | puts("inet_pton(): Error setting multicast address"); 548 | exit(EXIT_FAILURE); 549 | } 550 | 551 | FD_ZERO(&sset); 552 | FD_SET(idata.fd, &sset); 553 | 554 | lastprobe.tv_sec= 0; 555 | lastprobe.tv_usec=0; 556 | idata.pending_write_f=TRUE; 557 | 558 | /* The end_f flag is set after the last probe has been sent and a timeout period has elapsed. 559 | That is, we give responses enough time to come back 560 | */ 561 | while(!end_f){ 562 | rset= sset; 563 | wset= sset; 564 | eset= sset; 565 | 566 | if(!donesending_f){ 567 | /* This is the retransmission timer */ 568 | timeout.tv_sec= 1; 569 | timeout.tv_usec= 0; 570 | } 571 | else{ 572 | /* XXX: This should use the parameter from command line */ 573 | timeout.tv_sec= idata.local_timeout; 574 | timeout.tv_usec=0; 575 | } 576 | 577 | /* 578 | Check for readability and exceptions. We only check for writeability if there is pending data 579 | to send. 580 | */ 581 | if((sel=select(idata.fd+1, &rset, (idata.pending_write_f?&wset:NULL), &eset, &timeout)) == -1){ 582 | if(errno == EINTR){ 583 | continue; 584 | } 585 | else{ 586 | perror("iot-scan:"); 587 | exit(EXIT_FAILURE); 588 | } 589 | } 590 | 591 | if(gettimeofday(&curtime, NULL) == -1){ 592 | if(idata.verbose_f) 593 | perror("iot-scan"); 594 | 595 | exit(EXIT_FAILURE); 596 | } 597 | 598 | /* Check whether we have finished probing all targets */ 599 | if(donesending_f){ 600 | /* 601 | Just wait for SELECT_TIMEOUT seconds for any incoming responses. 602 | */ 603 | 604 | if(is_time_elapsed(&curtime, &lastprobe, idata.local_timeout * 1000000)){ 605 | end_f=TRUE; 606 | } 607 | } 608 | 609 | 610 | if(sel && FD_ISSET(idata.fd, &rset)){ 611 | /* XXX: Process response packet */ 612 | 613 | if( (nreadbuff = recvfrom(idata.fd, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 614 | perror("iot-scan: "); 615 | exit(EXIT_FAILURE); 616 | } 617 | /* puts("Got response"); */ 618 | 619 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 620 | perror("iot-scan: "); 621 | exit(EXIT_FAILURE); 622 | } 623 | 624 | /* Compare response with known one */ 625 | if(nreadbuff == sizeof(TP_LINK_IP_CAMERA_RESPONSE)){ 626 | if(memcmp(readbuff, TP_LINK_IP_CAMERA_RESPONSE, nreadbuff) == 0){ 627 | printf("%s # camera: TP-Link IP camera\n", pv4addr); 628 | } 629 | else{ 630 | /* puts("Incorrect response"); */ 631 | } 632 | } 633 | else{ 634 | /* puts("Incorrect size"); */ 635 | } 636 | } 637 | 638 | 639 | if(!donesending_f && !idata.pending_write_f && is_time_elapsed(&curtime, &lastprobe, 1 * 1000000)){ 640 | idata.pending_write_f=TRUE; 641 | continue; 642 | } 643 | 644 | if(!donesending_f && idata.pending_write_f && FD_ISSET(idata.fd, &wset)){ 645 | idata.pending_write_f=FALSE; 646 | 647 | /* XXX: SEND PROBE PACKET */ 648 | 649 | /* XXX: Will not happen, still check in case code is changed */ 650 | if(sizeof(TP_LINK_IP_CAMERA_DISCOVER) > sizeof(sendbuff)){ 651 | puts("Internal buffer too short"); 652 | exit(EXIT_FAILURE); 653 | } 654 | 655 | nsendbuff= sizeof(TP_LINK_IP_CAMERA_DISCOVER); 656 | memcpy(sendbuff, TP_LINK_IP_CAMERA_DISCOVER, nsendbuff); 657 | 658 | /* 659 | if( sendto(idata.fd, encrypted, sizeof(encrypted), 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 660 | perror("iot-scan: "); 661 | exit(EXIT_FAILURE); 662 | } 663 | */ 664 | 665 | if( sendto(idata.fd, sendbuff, nsendbuff, 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 666 | perror("iot-scan: "); 667 | exit(EXIT_FAILURE); 668 | } 669 | 670 | if(gettimeofday(&lastprobe, NULL) == -1){ 671 | if(idata.verbose_f) 672 | perror("iot-scan"); 673 | 674 | exit(EXIT_FAILURE); 675 | } 676 | 677 | retrans++; 678 | 679 | if(retrans >= idata.local_retrans) 680 | donesending_f= 1; 681 | 682 | } 683 | 684 | 685 | if(FD_ISSET(idata.fd, &eset)){ 686 | if(idata.verbose_f) 687 | puts("iot-scan: Found exception on descriptor"); 688 | 689 | exit(EXIT_FAILURE); 690 | } 691 | } 692 | } 693 | 694 | } 695 | 696 | exit(EXIT_SUCCESS); 697 | } 698 | 699 | 700 | 701 | 702 | /* 703 | * Function: match_strings() 704 | * 705 | * Checks whether one string "matches" within another string 706 | */ 707 | 708 | int match_strings(char *buscar, char *buffer){ 709 | unsigned int buscars, buffers; 710 | unsigned int i=0, j=0; 711 | 712 | buscars= Strnlen(buscar, MAX_IEEE_OUIS_LINE_SIZE); 713 | buffers= Strnlen(buffer, MAX_IEEE_OUIS_LINE_SIZE); 714 | 715 | if(buscars > buffers) 716 | return(0); 717 | 718 | while(i <= (buffers - buscars)){ 719 | j=0; 720 | 721 | while(j < buscars){ 722 | if(toupper((int) ((unsigned char)buscar[j])) != toupper((int) ((unsigned char)buffer[i+j]))) 723 | break; 724 | 725 | j++; 726 | } 727 | 728 | if(j >= buscars) 729 | return(1); 730 | 731 | i++; 732 | } 733 | 734 | return(0); 735 | } 736 | 737 | 738 | 739 | 740 | 741 | /* 742 | * Function: usage() 743 | * 744 | * Prints the syntax of the iot-scan tool 745 | */ 746 | 747 | void usage(void){ 748 | puts("usage: iot-scan (-L | -d) [-i INTERFACE] [-v] [-h]"); 749 | } 750 | 751 | 752 | /* 753 | * Function: print_help() 754 | * 755 | * Prints help information for the iot-scan tool 756 | */ 757 | 758 | void print_help(void){ 759 | puts(SI6_TOOLKIT); 760 | puts( "iot-scan: An IoT scanning tool\n"); 761 | usage(); 762 | 763 | puts("\nOPTIONS:\n" 764 | " --interface, -i Network interface\n" 765 | " --dst-address, -d IPv6 Destination Range or Prefix\n" 766 | " --retrans, -x Number of retransmissions of each probe\n" 767 | " --timeout, -O Timeout in seconds (default: 1 second)\n" 768 | " --local-scan, -L Scan the local subnet\n" 769 | " --help, -h Print help for the iot-scan tool\n" 770 | " --verbose, -v Be verbose\n" 771 | "\n" 772 | " Programmed by Fernando Gont for SI6 Networks \n" 773 | " Please send any bug reports to \n" 774 | ); 775 | } 776 | 777 | 778 | 779 | /* 780 | * Function: print_host_entries() 781 | * 782 | * Prints the IPv6 addresses (and optionally the Ethernet addresses) in a list 783 | */ 784 | 785 | int print_host_entries(struct host_list *hlist, unsigned char flag){ 786 | unsigned int i; 787 | 788 | for(i=0; i < (hlist->nhosts); i++){ 789 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 790 | if(verbose_f>1) 791 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 792 | 793 | return(-1); 794 | } 795 | 796 | if(flag == PRINT_ETHER_ADDR){ 797 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 798 | if(verbose_f>1) 799 | puts("ether_ntop(): Error converting address"); 800 | 801 | return(-1); 802 | } 803 | 804 | printf("%s @ %s\n", pv6addr, plinkaddr); 805 | } 806 | else 807 | printf("%s\n", pv6addr); 808 | } 809 | 810 | return 0; 811 | } 812 | 813 | 814 | 815 | /* 816 | * Function: print_unique_host_entries() 817 | * 818 | * Prints only one IPv6 address (and optionally the Ethernet addresses) per Ethernet 819 | * address in a list. 820 | */ 821 | 822 | int print_unique_host_entries(struct host_list *hlist, unsigned char flag){ 823 | unsigned int i, j, k; 824 | 825 | for(i=0; i < (hlist->nhosts); i++){ 826 | 827 | if(i){ 828 | for(j=0; j < i; j++){ 829 | for(k=0; k < ETH_ALEN; k++){ 830 | if((hlist->host[i])->ether.a[k] != (hlist->host[j])->ether.a[k]) 831 | break; 832 | } 833 | 834 | if(k == ETH_ALEN) 835 | break; 836 | } 837 | 838 | if(j < i) 839 | continue; 840 | } 841 | 842 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 843 | if(verbose_f>1) 844 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 845 | 846 | return(-1); 847 | } 848 | 849 | if(flag == PRINT_ETHER_ADDR){ 850 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 851 | if(verbose_f>1) 852 | puts("ether_ntop(): Error converting address"); 853 | 854 | return(-1); 855 | } 856 | 857 | printf("%s @ %s\n", pv6addr, plinkaddr); 858 | } 859 | else 860 | printf("%s\n", pv6addr); 861 | } 862 | 863 | return 0; 864 | } 865 | 866 | 867 | 868 | /* 869 | * Function: free_host_entries() 870 | * 871 | * Releases memory allocated for holding IPv6 addresses and Ethernet addresses 872 | */ 873 | 874 | void free_host_entries(struct host_list *hlist){ 875 | unsigned int i; 876 | 877 | for(i=0; i< hlist->nhosts; i++) 878 | free(hlist->host[i]); 879 | 880 | hlist->nhosts=0; /* Set the number of entries to 0, to reflect the released memory */ 881 | return; 882 | } 883 | 884 | 885 | 886 | 887 | -------------------------------------------------------------------------------- /tools/iot-scan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the iot-scanner tool 3 | * 4 | */ 5 | 6 | #define BUFFER_SIZE 65556 7 | 8 | /* Constants used with the multi_scan_local() function */ 9 | #define PROBE_ICMP6_ECHO 1 10 | #define PROBE_UNREC_OPT 2 11 | #define PROBE_TCP 3 12 | #define LOCAL_SRC 1 13 | #define GLOBAL_SRC 2 14 | 15 | #define ICMPV6_ECHO_PAYLOAD_SIZE 56 16 | #define MAX_IPV6_ENTRIES 65000 17 | 18 | /* Constant for the host-scanning functions */ 19 | #define PRINT_ETHER_ADDR 1 20 | #define NOT_PRINT_ETHER_ADDR 0 21 | 22 | #define VALID_MAPPING 1 23 | #define INVALID_MAPPING 0 24 | 25 | 26 | /* Remote scans */ 27 | #define LOW_BYTE_1ST_WORD_UPPER 0x1500 28 | #define LOW_BYTE_2ND_WORD_UPPER 0x0100 29 | #define EMBEDDED_PORT_2ND_WORD 5 30 | #define MAX_IEEE_OUIS_LINE_SIZE 160 31 | #define OUI_HEX_STRING_SIZE 5 32 | #define MAX_IEEE_OUIS 1000 33 | #define MAX_SCAN_ENTRIES 65535 34 | #define MAX_PORT_ENTRIES 65536 35 | #define MAX_PREF_ENTRIES MAX_SCAN_ENTRIES 36 | #define SELECT_TIMEOUT 4 37 | #define PSCAN_TIMEOUT 1 38 | #define MAX_RANGE_STR_LEN 79 39 | #define MIN_INC_RANGE 1000 40 | /* #define MAX_DESTNATIONS 65535 */ 41 | #define MAX_IID_ENTRIES 65535 42 | 43 | #define ND_RETRIES 0 44 | 45 | /* Constants for config file processing */ 46 | #define MAX_LINE_SIZE 250 47 | #define MAX_VAR_NAME_LEN 100 48 | #define MAX_FILENAME_SIZE 250 49 | 50 | 51 | union my6_addr{ 52 | uint8_t s6addr[16]; 53 | uint16_t s6addr16[8]; 54 | uint32_t s6addr32[4]; 55 | struct in6_addr in6_addr; 56 | }; 57 | 58 | 59 | #define MAX_PORTS_LINE_SIZE 80 60 | 61 | 62 | 63 | /* Constants for port scan results */ 64 | 65 | #define PORT_FILTERED 1 66 | #define PORT_OPEN 2 67 | #define PORT_CLOSED 4 68 | #define PORT_ACT_FILT 8 69 | 70 | 71 | #define DEFAULT_MIN_PORT 0 72 | #define DEFAULT_MAX_PORT 65535 73 | #define MAX_PORT_RANGE 65536 74 | #define IPPROTO_ALL 0xf1 /* Fake number to indicate both TCP and UDP */ 75 | 76 | /* Constants for printing the scanning results */ 77 | 78 | /* Steps into which results will be printed */ 79 | #define MAX_STEPS 20 80 | 81 | #define SCAN_SMART_PLUGS 0x00000001 82 | #define SCAN_IP_CAMERAS 0x00000002 83 | #define SCAN_ALL (SCAN_SMART_PLUGS | SCAN_IP_CAMERAS) 84 | 85 | 86 | #define GENIUS_IP_CAMERA_SERVICE_PORT 32761 87 | #define GENIUS_IP_CAMERA_SENDING_PORT 16353 88 | 89 | 90 | char TP_LINK_SMART_DISCOVER[]="{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}"; 91 | char TP_LINK_IP_CAMERA_DISCOVER[]={0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x17, 0x00, \ 92 | 0x07, 0xd8, 0xa1, 0x4f, 0xc2, 0x90, 0x98, 0x93, 0xec, 0x5b, 0x80, 0x5e, \ 93 | 0xfa, 0xe2, 0x06, 0xd5, 0x63, 0x86, 0xb6, 0xdc, 0x3c, 0x8a, 0xff, 0x48, \ 94 | 0xce, 0x6c, 0xbd, 0x97, 0xb7, 0x1c, 0x21, 0xe9, 0xbd, 0x59, 0x30, 0xd7, \ 95 | 0x19, 0xd1, 0x22, 0x77, 0x6b, 0xd9, 0x43, 0x19, 0xd8, 0x87, 0x9f, 0xbb}; 96 | 97 | char TP_LINK_IP_CAMERA_RESPONSE[]= {0x02, 0x03, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 98 | 0x17, 0x00, 0x72, 0xa9, 0xa2, 0x32, 0xad, 0xd8, 0x65, 0xae, \ 99 | 0x78, 0x40, 0xad, 0x62, 0x08, 0xf9, 0x34, 0x16}; 100 | 101 | 102 | 103 | char GENIUS_IP_CAMERA_DISCOVER[]={0x6e, 0x4c, 0x9d, 0x8c, 0x40, 0xd1, 0x40, 0xda, 0x2d, 0x2d, 0x68, 0x2c, \ 104 | 0x00, 0xe4, 0xca, 0xda, 0x6e, 0x2e, 0x8d, 0x8c, 0x40, 0xd0, 0x40, 0xca, \ 105 | 0x2d, 0x6d, 0x28, 0x0c, 0x40, 0xe4, 0xca, 0xd8, 0x6e, 0x2e, 0x8d, 0x8c, \ 106 | 0x40, 0xd0, 0x40, 0xca, 0x2d, 0x6d, 0x28, 0x0c, 0x40, 0xe4, 0xca, 0xd8, \ 107 | 0x61, 0x72, 0x43, 0x68}; 108 | 109 | 110 | char GENIUS_IP_CAMERA_RESPONSE[]={0x4e, 0x4f, 0x8d, 0xac, 0x40, 0xd0, 0x40, 0xca, 0x3d, 0x2d, 0x68, 0x2c, \ 111 | 0x00, 0xe6, 0xca, 0xda, 0x5a, 0x2d, 0xae, 0x41, 0x0d, 0xd5, 0x55, 0xcf, \ 112 | 0x6e, 0x23, 0x6c, 0x4f, 0xd4, 0xbd, 0xce, 0x5b, 0x42, 0xbe, 0x97, 0x8c, \ 113 | 0x12, 0xd0, 0x40, 0xca, 0x28, 0x26, 0x0d, 0x29, 0x66, 0xae, 0xf1, 0xd8, \ 114 | 0x61, 0x72, 0x43, 0x68}; 115 | 116 | 117 | 118 | #define EDIMAX_SMART_PLUG_SERVICE_PORT 20560 119 | char EDIMAX_SMART_PLUG_DISCOVER[]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0x44, 0x49, 0x4d, 0x41, 0x58, \ 120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xff, 0x5e}; 121 | 122 | 123 | #define EDIMAX_MAC_LEN 6 124 | #define EDIMAX_MAN_LEN 12 125 | #define EDIMAX_MOD_LEN 14 126 | #define EDIMAX_VER_LEN 8 127 | #define EDIMAX_DIS_LEN 128 128 | #define EDIMAX_IP_LEN 4 129 | 130 | 131 | struct edimax_discover_response { 132 | unsigned char macaddr[EDIMAX_MAC_LEN]; /* 6 */ 133 | char manufacturer[EDIMAX_MAN_LEN]; /* 12 */ 134 | uint32_t unknown; /* 0x 01 a1 fe 5e */ 135 | char model[EDIMAX_MOD_LEN]; /* 14 */ 136 | char version[EDIMAX_VER_LEN]; /* 8 */ 137 | char displayname[EDIMAX_DIS_LEN]; /* 128 */ 138 | uint16_t port; /* 0x10 27 == 10000 little endian */ 139 | unsigned char ipaddr[EDIMAX_IP_LEN]; /* 4 */ 140 | uint32_t unknown2; 141 | unsigned char raddr[EDIMAX_IP_LEN]; /* 4 */ 142 | } __attribute__ ((__packed__)); 143 | 144 | 145 | -------------------------------------------------------------------------------- /tools/iot-scan.h~: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the iot-scanner tool 3 | * 4 | */ 5 | 6 | #define BUFFER_SIZE 65556 7 | 8 | /* Constants used with the multi_scan_local() function */ 9 | #define PROBE_ICMP6_ECHO 1 10 | #define PROBE_UNREC_OPT 2 11 | #define PROBE_TCP 3 12 | #define LOCAL_SRC 1 13 | #define GLOBAL_SRC 2 14 | 15 | #define ICMPV6_ECHO_PAYLOAD_SIZE 56 16 | #define MAX_IPV6_ENTRIES 65000 17 | 18 | /* Constant for the host-scanning functions */ 19 | #define PRINT_ETHER_ADDR 1 20 | #define NOT_PRINT_ETHER_ADDR 0 21 | 22 | #define VALID_MAPPING 1 23 | #define INVALID_MAPPING 0 24 | 25 | 26 | /* Remote scans */ 27 | #define LOW_BYTE_1ST_WORD_UPPER 0x1500 28 | #define LOW_BYTE_2ND_WORD_UPPER 0x0100 29 | #define EMBEDDED_PORT_2ND_WORD 5 30 | #define MAX_IEEE_OUIS_LINE_SIZE 160 31 | #define OUI_HEX_STRING_SIZE 5 32 | #define MAX_IEEE_OUIS 1000 33 | #define MAX_SCAN_ENTRIES 65535 34 | #define MAX_PORT_ENTRIES 65536 35 | #define MAX_PREF_ENTRIES MAX_SCAN_ENTRIES 36 | #define SELECT_TIMEOUT 4 37 | #define PSCAN_TIMEOUT 1 38 | #define MAX_RANGE_STR_LEN 79 39 | #define MIN_INC_RANGE 1000 40 | /* #define MAX_DESTNATIONS 65535 */ 41 | #define MAX_IID_ENTRIES 65535 42 | 43 | #define ND_RETRIES 0 44 | 45 | /* Constants for config file processing */ 46 | #define MAX_LINE_SIZE 250 47 | #define MAX_VAR_NAME_LEN 100 48 | #define MAX_FILENAME_SIZE 250 49 | 50 | 51 | union my6_addr{ 52 | uint8_t s6addr[16]; 53 | uint16_t s6addr16[8]; 54 | uint32_t s6addr32[4]; 55 | struct in6_addr in6_addr; 56 | }; 57 | 58 | 59 | #define MAX_PORTS_LINE_SIZE 80 60 | 61 | 62 | 63 | /* Constants for port scan results */ 64 | 65 | #define PORT_FILTERED 1 66 | #define PORT_OPEN 2 67 | #define PORT_CLOSED 4 68 | #define PORT_ACT_FILT 8 69 | 70 | 71 | #define DEFAULT_MIN_PORT 0 72 | #define DEFAULT_MAX_PORT 65535 73 | #define MAX_PORT_RANGE 65536 74 | #define IPPROTO_ALL 0xf1 /* Fake number to indicate both TCP and UDP */ 75 | 76 | /* Constants for printing the scanning results */ 77 | 78 | /* Steps into which results will be printed */ 79 | #define MAX_STEPS 20 80 | 81 | #define SMART_PLUGS 0x00000001 82 | #define IP_CAMERAS 0x00000002 83 | 84 | -------------------------------------------------------------------------------- /tools/iot-tddp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * iot-tddp: An implementation of TDDP 3 | * 4 | * Copyright (C) 2017 Fernando Gont 5 | * 6 | * Programmed by Fernando Gont for SI6 Networks 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * Build with: make iot-tddp 22 | * 23 | * It requires that the libpcap and the openssl libraries be installed 24 | * on your system. 25 | * 26 | * Please send any bug reports to Fernando Gont 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #include "iot-tddp.h" 58 | #include "iot-toolkit.h" 59 | #include "libiot.h" 60 | 61 | /* #define DEBUG */ 62 | 63 | /* Function prototypes */ 64 | void init_packet_data(struct iface_data *); 65 | void free_host_entries(struct host_list *); 66 | int host_scan_local(pcap_t *, struct iface_data *, struct in6_addr *, unsigned char, \ 67 | struct host_entry *); 68 | void print_help(void); 69 | int print_host_entries(struct host_list *, unsigned char); 70 | void local_sig_alarm(int); 71 | void usage(void); 72 | int process_config_file(const char *); 73 | 74 | /* Used for multiscan */ 75 | struct host_list host_local, host_global, host_candidate; 76 | struct host_entry *host_locals[MAX_IPV6_ENTRIES], *host_globals[MAX_IPV6_ENTRIES]; 77 | struct host_entry *host_candidates[MAX_IPV6_ENTRIES]; 78 | 79 | /* Used for router discovery */ 80 | struct iface_data idata; 81 | 82 | /* Variables used for learning the default router */ 83 | struct ether_addr router_ether, rs_ether; 84 | struct in6_addr router_ipv6, rs_ipv6; 85 | 86 | struct in6_addr randprefix; 87 | unsigned char randpreflen; 88 | 89 | bpf_u_int32 my_netmask; 90 | bpf_u_int32 my_ip; 91 | struct bpf_program pcap_filter; 92 | char dev[64], errbuf[PCAP_ERRBUF_SIZE]; 93 | unsigned char buffer[BUFFER_SIZE], buffrh[MIN_IPV6_HLEN + MIN_TCP_HLEN]; 94 | char readbuff[BUFFER_SIZE], sendbuff[BUFFER_SIZE]; 95 | ssize_t nreadbuff, nsendbuff; 96 | char line[LINE_BUFFER_SIZE]; 97 | unsigned char *v6buffer, *ptr, *startofprefixes; 98 | char *pref; 99 | 100 | struct ether_header *ethernet; 101 | unsigned int ndst=0; 102 | 103 | char *lasts, *rpref; 104 | char *charptr; 105 | 106 | size_t nw; 107 | unsigned long ul_res, ul_val; 108 | unsigned int i, j, startrand; 109 | unsigned int skip; 110 | unsigned char dstpreflen; 111 | 112 | uint16_t mask; 113 | 114 | char plinkaddr[ETHER_ADDR_PLEN], pv4addr[INET_ADDRSTRLEN]; 115 | char pv6addr[INET6_ADDRSTRLEN]; 116 | unsigned char verbose_f=FALSE; 117 | unsigned char dstaddr_f=FALSE, timestamps_f=FALSE, scan_local_f=FALSE; 118 | 119 | 120 | 121 | unsigned char dst_f=FALSE, end_f=FALSE, endpscan_f=FALSE; 122 | unsigned char donesending_f=FALSE; 123 | uint16_t srcport, dstport; 124 | uint32_t scan_type; 125 | char scan_type_f=FALSE; 126 | unsigned long pktinterval, rate; 127 | unsigned int packetsize; 128 | 129 | struct prefixv4_entry prefix; 130 | 131 | char *charstart, *charend, *lastcolon; 132 | unsigned int nsleep; 133 | int sel; 134 | fd_set srset, swset, seset, rset, wset, eset; 135 | struct timeval curtime, pcurtime, lastprobe; 136 | struct tm pcurtimetm; 137 | unsigned int retrans=0; 138 | 139 | int main(int argc, char **argv){ 140 | extern char *optarg; 141 | int r; 142 | struct addrinfo hints, *res, *aiptr; 143 | struct target_ipv6 target; 144 | struct timeval timeout; 145 | void *voidptr; 146 | const int on=1; 147 | struct sockaddr_in sockaddr_in, sockaddr_from, sockaddr_to; 148 | socklen_t sockaddrfrom_len; 149 | struct tddp_hdr *tddp_hdr; 150 | unsigned int npayload=0; 151 | 152 | char username_admin[]="admin"; 153 | char password_admin[]="admin"; 154 | char *username; 155 | char *password; 156 | unsigned int nusername; 157 | unsigned int npassword; 158 | char preparekey[BUFFER_SIZE]; 159 | char keydigest[MD5_DIGEST_LENGTH]; 160 | DES_cblock des_key[8]; 161 | DES_key_schedule key; 162 | uint8_t tddp_version=2; 163 | 164 | /* 165 | # 0x01 SET_USR_CFG - set configuration information 166 | # 0x02 GET_SYS_INF - get configuration information 167 | # 0x03 CMD_SPE_OPR - special configuration commands 168 | # 0x04 HEART_BEAT - the heartbeat package 169 | */ 170 | uint8_t tddp_type= 0x03; /* GETSYSINF*/ 171 | 172 | /* 173 | ## Code Request Type 174 | # 0x01 TDDP_REQUEST 175 | # 0x02 TDDP_REPLY 176 | tddp_code = "01" 177 | */ 178 | uint8_t tddp_code=0x01; 179 | 180 | /* 181 | ## Reply Info Status 182 | # 0x00 REPLY_OK 183 | # 0x02 ? 184 | # 0x03 ? 185 | # 0x09 REPLY_ERROR 186 | # 0xFF ? 187 | tddp_reply = "00" 188 | */ 189 | uint8_t tddp_replyinfo= 0x00; 190 | uint16_t tddp_pktid= 0x0020; 191 | uint8_t tddp_subtype= 0x00; 192 | MD5_CTX mdContext; 193 | 194 | static struct option longopts[] = { 195 | {"interface", required_argument, 0, 'i'}, 196 | {"pktid", required_argument, 0, 'I'}, 197 | {"code", required_argument, 0, 'c'}, 198 | {"dst-address", required_argument, 0, 'd'}, 199 | {"scan", no_argument, 0, 'Z'}, 200 | {"retrans", required_argument, 0, 'x'}, 201 | {"timeout", required_argument, 0, 'O'}, 202 | {"subtype", required_argument, 0, 't'}, 203 | {"type", required_argument, 0, 'T'}, 204 | {"user", required_argument, 0, 'u'}, 205 | {"src-port", required_argument, 0, 'o'}, 206 | {"dst-port", required_argument, 0, 'a'}, 207 | {"password", required_argument, 0, 'p'}, 208 | {"replyinfo", required_argument, 0, 'r'}, 209 | {"verbose", no_argument, 0, 'v'}, 210 | {"version", required_argument, 0, 'V'}, 211 | {"help", no_argument, 0, 'h'}, 212 | {0, 0, 0, 0 } 213 | }; 214 | 215 | char shortopts[]= "i:I:c:d:Zx:O:t:T:u:o:a:p:r:vV:h"; 216 | 217 | char option; 218 | 219 | if(argc<=1){ 220 | usage(); 221 | exit(EXIT_FAILURE); 222 | } 223 | 224 | srandom(time(NULL)); 225 | 226 | init_iface_data(&idata); 227 | 228 | /* Set defaults */ 229 | username= username_admin; 230 | password= password_admin; 231 | tddp_type= 0x03; /* GETSYSINF*/ 232 | tddp_code=0x01; 233 | tddp_replyinfo= 0x00; 234 | tddp_pktid= 0x0020; 235 | tddp_subtype= 0x00; 236 | 237 | 238 | 239 | while((r=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 240 | option= r; 241 | 242 | switch(option) { 243 | case 'i': /* Interface */ 244 | strncpy(idata.iface, optarg, IFACE_LENGTH-1); 245 | idata.iface[IFACE_LENGTH-1]=0; 246 | idata.ifindex= if_nametoindex(idata.iface); 247 | idata.iface_f=TRUE; 248 | break; 249 | 250 | case 'I': 251 | tddp_pktid=atoi(optarg); 252 | break; 253 | 254 | case 'c': 255 | tddp_code=atoi(optarg); 256 | break; 257 | 258 | case 't': 259 | tddp_subtype=atoi(optarg); 260 | break; 261 | 262 | case 'T': 263 | tddp_type=atoi(optarg); 264 | break; 265 | 266 | case 'V': 267 | tddp_version=atoi(optarg); 268 | break; 269 | 270 | case 'u': 271 | username= optarg; 272 | break; 273 | 274 | case 'p': 275 | password= optarg; 276 | break; 277 | 278 | case 'r': 279 | tddp_replyinfo=atoi(optarg); 280 | break; 281 | 282 | case 'd': /* IPv6 Destination Address/Prefix */ 283 | /* The '-d' option contains a domain name */ 284 | if((charptr = strtok_r(optarg, "/", &lasts)) == NULL){ 285 | puts("Error in Destination Address"); 286 | exit(EXIT_FAILURE); 287 | } 288 | 289 | strncpy(target.name, charptr, NI_MAXHOST); 290 | target.name[NI_MAXHOST-1]=0; 291 | 292 | if((charptr = strtok_r(NULL, " ", &lasts)) != NULL){ 293 | prefix.len = atoi(charptr); 294 | 295 | if(prefix.len > 32){ 296 | puts("Prefix length error in IP Destination Address"); 297 | exit(EXIT_FAILURE); 298 | } 299 | } 300 | else{ 301 | prefix.len= 32; 302 | } 303 | 304 | memset(&hints, 0, sizeof(hints)); 305 | hints.ai_family= AF_INET; 306 | hints.ai_canonname = NULL; 307 | hints.ai_addr = NULL; 308 | hints.ai_next = NULL; 309 | hints.ai_socktype= SOCK_DGRAM; 310 | 311 | if( (target.res = getaddrinfo(target.name, NULL, &hints, &res)) != 0){ 312 | printf("Unknown Destination '%s': %s\n", target.name, gai_strerror(target.res)); 313 | exit(1); 314 | } 315 | 316 | for(aiptr=res; aiptr != NULL; aiptr=aiptr->ai_next){ 317 | if(aiptr->ai_family != AF_INET) 318 | continue; 319 | 320 | if(aiptr->ai_addrlen != sizeof(struct sockaddr_in)) 321 | continue; 322 | 323 | if(aiptr->ai_addr == NULL) 324 | continue; 325 | 326 | prefix.ip= ( (struct sockaddr_in *)aiptr->ai_addr)->sin_addr; 327 | } 328 | 329 | freeaddrinfo(res); 330 | 331 | idata.dstaddr= prefix.ip; 332 | idata.dstaddr_f= TRUE; 333 | dst_f=TRUE; 334 | break; 335 | 336 | case 'L': 337 | scan_local_f=TRUE; 338 | break; 339 | 340 | case 'x': 341 | idata.local_retrans=atoi(optarg); 342 | break; 343 | 344 | case 'o': /* UDP Source Port */ 345 | idata.srcport= atoi(optarg); 346 | idata.srcport_f= 1; 347 | break; 348 | 349 | case 'a': /* UDP Destination Port */ 350 | idata.dstport= atoi(optarg); 351 | idata.dstport_f= 1; 352 | break; 353 | 354 | case 'O': 355 | idata.local_timeout=atoi(optarg); 356 | break; 357 | 358 | case 'v': /* Be verbose */ 359 | idata.verbose_f++; 360 | break; 361 | 362 | case 'h': /* Help */ 363 | print_help(); 364 | exit(EXIT_FAILURE); 365 | break; 366 | 367 | default: 368 | usage(); 369 | exit(EXIT_FAILURE); 370 | break; 371 | 372 | } /* switch */ 373 | } /* while(getopt) */ 374 | 375 | 376 | nusername= Strnlen(username, BUFFER_SIZE); 377 | npassword= Strnlen(password, BUFFER_SIZE); 378 | 379 | if( (nusername+npassword+2) > BUFFER_SIZE){ 380 | puts("Username/password too long"); 381 | exit(EXIT_FAILURE); 382 | } 383 | 384 | strncpy(preparekey, username, nusername); 385 | strncpy( (char *)preparekey + nusername, password, npassword); 386 | /* Preparekey now contains the concatenated username and assword */ 387 | 388 | MD5_Init(&mdContext); 389 | MD5_Update(&mdContext, preparekey, nusername+npassword); 390 | MD5_Final((unsigned char *)keydigest, &mdContext); 391 | 392 | memcpy(des_key, keydigest, 8); 393 | 394 | 395 | /* 396 | XXX: This is rather ugly, but some local functions need to check for verbosity, and it was not warranted 397 | to pass &idata as an argument 398 | */ 399 | verbose_f= idata.verbose_f; 400 | 401 | if(geteuid()){ 402 | puts("iot-tddp needs superuser privileges to run"); 403 | exit(EXIT_FAILURE); 404 | } 405 | 406 | if(scan_local_f && !idata.iface_f){ 407 | /* XXX This should later allow to just specify local scan and automatically choose an interface */ 408 | /* puts("Must specify the network interface with the -i option when a local scan is selected"); */ 409 | /* exit(EXIT_FAILURE); */ 410 | } 411 | 412 | if(!dst_f && !scan_local_f){ 413 | if(idata.verbose_f) 414 | puts("Must specify either a destination prefix ('-d'), or a local scan ('-L')"); 415 | 416 | exit(EXIT_FAILURE); 417 | } 418 | 419 | release_privileges(); 420 | 421 | if(get_local_addrs(&idata) == FAILURE){ 422 | puts("Error obtaining list of local interfaces and addresses"); 423 | exit(EXIT_FAILURE); 424 | } 425 | 426 | if(scan_local_f){ 427 | /* If an interface was specified, we select an IPv4 address from such interface */ 428 | if(idata.iface_f){ 429 | if( (voidptr=find_v4addr_for_iface(&(idata.iflist), idata.iface)) == NULL){ 430 | printf("No IPv4 address for interface %s\n", idata.iface); 431 | exit(EXIT_FAILURE); 432 | } 433 | 434 | idata.srcaddr= *((struct in_addr *) voidptr); 435 | } 436 | else{ 437 | if( (voidptr=find_v4addr(&(idata.iflist))) == NULL){ 438 | puts("No IPv4 address available on local host"); 439 | exit(EXIT_FAILURE); 440 | } 441 | 442 | idata.srcaddr= *((struct in_addr *)voidptr); 443 | } 444 | 445 | if( (idata.fd=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 446 | puts("Could not create socket"); 447 | exit(EXIT_FAILURE); 448 | } 449 | 450 | if( setsockopt(idata.fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1){ 451 | puts("Error while setting SO_BROADCAST socket option"); 452 | exit(EXIT_FAILURE); 453 | } 454 | 455 | memset(&sockaddr_in, 0, sizeof(sockaddr_in)); 456 | sockaddr_in.sin_family= AF_INET; 457 | sockaddr_in.sin_port= 0; /* Allow Sockets API to set an ephemeral port */ 458 | sockaddr_in.sin_addr= idata.srcaddr; 459 | 460 | if(bind(idata.fd, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1){ 461 | puts("Error bind()ing socket to local address"); 462 | exit(EXIT_FAILURE); 463 | } 464 | 465 | /* Second (receive) socket */ 466 | if( (idata.fd2=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 467 | puts("Could not create socket"); 468 | exit(EXIT_FAILURE); 469 | } 470 | 471 | memset(&sockaddr_in, 0, sizeof(sockaddr_in)); 472 | sockaddr_in.sin_family= AF_INET; 473 | if(idata.srcport_f){ 474 | sockaddr_in.sin_port= htons(idata.srcport); /* Allow Sockets API to set an ephemeral port */ 475 | } 476 | else{ 477 | sockaddr_in.sin_port= htons(TDDP_RECEIVE_PORT); /* Allow Sockets API to set an ephemeral port */ 478 | } 479 | 480 | sockaddr_in.sin_addr= idata.srcaddr; 481 | 482 | if(bind(idata.fd2, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1){ 483 | puts("Error bind()ing socket to local address"); 484 | exit(EXIT_FAILURE); 485 | } 486 | 487 | memset(&sockaddr_to, 0, sizeof(sockaddr_to)); 488 | sockaddr_to.sin_family= AF_INET; 489 | 490 | if(idata.dstport_f){ 491 | sockaddr_to.sin_port= htons(idata.dstport); 492 | } 493 | else{ 494 | sockaddr_to.sin_port= htons(TDDP_SERVICE_PORT); 495 | } 496 | sockaddr_to.sin_addr= idata.dstaddr; 497 | 498 | memset(&sockaddr_from, 0, sizeof(sockaddr_from)); 499 | sockaddr_from.sin_family= AF_INET; 500 | sockaddrfrom_len=sizeof(sockaddr_from); 501 | tddp_hdr= (struct tddp_hdr *) sendbuff; 502 | memset(tddp_hdr, 0, sizeof(struct tddp_hdr)); 503 | 504 | tddp_hdr->version= tddp_version; 505 | tddp_hdr->type= tddp_type; 506 | tddp_hdr->code= tddp_code; 507 | tddp_hdr->replyinfo= tddp_replyinfo; 508 | tddp_hdr->pktid= tddp_pktid; 509 | tddp_hdr->subtype= tddp_subtype; 510 | tddp_hdr->res= 0x00; 511 | 512 | charptr= (char *) (sendbuff + sizeof(struct tddp_hdr));; 513 | /* here we should insert any data */ 514 | npayload= charptr- sendbuff - sizeof(struct tddp_hdr); 515 | 516 | /* XXX check bounds */ 517 | for(i=0; i < (npayload%8); i++){ 518 | *charptr= 0x00; 519 | charptr++; 520 | } 521 | 522 | 523 | nsendbuff= charptr- sendbuff; 524 | npayload= nsendbuff - sizeof(struct tddp_hdr); 525 | tddp_hdr->pktlength= htonl( (uint32_t)npayload); 526 | 527 | if(npayload){ 528 | ERR_clear_error(); 529 | 530 | if(DES_set_key(des_key, &key) < 0){ 531 | puts("Error setting up DES key"); 532 | exit(EXIT_FAILURE); 533 | } 534 | 535 | for(i=0; i< (npayload/8); i++){ 536 | DES_ecb_encrypt( (DES_cblock *) charptr, (DES_cblock *) charptr, &key, 1); 537 | charptr= charptr+8; 538 | } 539 | } 540 | 541 | /* Now compute MD5 checksum */ 542 | MD5_Init(&mdContext); 543 | MD5_Update(&mdContext, sendbuff, nsendbuff); 544 | MD5_Final (tddp_hdr->md5_digest ,&mdContext); 545 | puts("Sending TDDP Packet:"); 546 | print_tddp_packet(sendbuff, nsendbuff); 547 | 548 | if(!idata.dstaddr_f){ 549 | puts("Must specify destination address"); 550 | exit(EXIT_FAILURE); 551 | } 552 | 553 | 554 | FD_ZERO(&srset); 555 | FD_ZERO(&swset); 556 | FD_ZERO(&seset); 557 | 558 | FD_SET(idata.fd, &swset); 559 | FD_SET(idata.fd, &srset); 560 | FD_SET(idata.fd2, &srset); 561 | FD_SET(idata.fd, &seset); 562 | FD_SET(idata.fd2, &seset); 563 | 564 | lastprobe.tv_sec= 0; 565 | lastprobe.tv_usec=0; 566 | idata.pending_write_f=TRUE; 567 | 568 | /* The end_f flag is set after the last probe has been sent and a timeout period has elapsed. 569 | That is, we give responses enough time to come back 570 | */ 571 | while(!end_f){ 572 | rset= srset; 573 | wset= swset; 574 | eset= seset; 575 | 576 | if(!donesending_f){ 577 | /* This is the retransmission timer */ 578 | timeout.tv_sec= 1; 579 | timeout.tv_usec= 0; 580 | } 581 | else{ 582 | /* XXX: This should use the parameter from command line */ 583 | timeout.tv_sec= idata.local_timeout; 584 | timeout.tv_usec=0; 585 | } 586 | 587 | /* 588 | Check for readability and exceptions. We only check for writeability if there is pending data 589 | to send. 590 | */ 591 | if((sel=select(idata.fd2+1, &rset, (idata.pending_write_f?&wset:NULL), &eset, &timeout)) == -1){ 592 | if(errno == EINTR){ 593 | continue; 594 | } 595 | else{ 596 | perror("iot-tddp:"); 597 | exit(EXIT_FAILURE); 598 | } 599 | } 600 | 601 | if(gettimeofday(&curtime, NULL) == -1){ 602 | if(idata.verbose_f) 603 | perror("iot-tddp"); 604 | 605 | exit(EXIT_FAILURE); 606 | } 607 | 608 | /* Check whether we have finished probing all targets */ 609 | if(donesending_f){ 610 | /* 611 | Just wait for SELECT_TIMEOUT seconds for any incoming responses. 612 | */ 613 | 614 | if(is_time_elapsed(&curtime, &lastprobe, idata.local_timeout * 1000000)){ 615 | end_f=TRUE; 616 | } 617 | } 618 | 619 | 620 | if(sel && FD_ISSET(idata.fd2, &rset)){ 621 | /* XXX: Process response packet */ 622 | 623 | if( (nreadbuff = recvfrom(idata.fd2, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 624 | perror("iot-tddp: "); 625 | exit(EXIT_FAILURE); 626 | } 627 | 628 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 629 | perror("iot-tddp: "); 630 | exit(EXIT_FAILURE); 631 | } 632 | 633 | printf("Read %u bytes from %s\n", (unsigned int)nreadbuff, pv4addr); 634 | print_tddp_packet(readbuff, nreadbuff); 635 | } 636 | 637 | if(sel && FD_ISSET(idata.fd, &rset)){ 638 | /* XXX: Process response packet */ 639 | 640 | if( (nreadbuff = recvfrom(idata.fd, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 641 | perror("iot-tddp: "); 642 | exit(EXIT_FAILURE); 643 | } 644 | 645 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 646 | perror("iot-tddp: "); 647 | exit(EXIT_FAILURE); 648 | } 649 | 650 | /* There's data to be desencrypted */ 651 | if(nreadbuff> sizeof(struct tddp_hdr)){ 652 | for(i=0; i< ((nreadbuff-sizeof(struct tddp_hdr))/8); i++){ 653 | DES_ecb_encrypt( (DES_cblock *)(readbuff+ sizeof(struct tddp_hdr) + i * 8), \ 654 | (DES_cblock *)(readbuff+ sizeof(struct tddp_hdr) + i * 8), &key, 0); 655 | } 656 | } 657 | 658 | printf("Read %u bytes from %s\n", (unsigned int)nreadbuff, pv4addr); 659 | print_tddp_packet(readbuff, nreadbuff); 660 | } 661 | 662 | 663 | if(!donesending_f && !idata.pending_write_f && is_time_elapsed(&curtime, &lastprobe, 1 * 1000000)){ 664 | idata.pending_write_f=TRUE; 665 | continue; 666 | } 667 | 668 | if(!donesending_f && idata.pending_write_f && FD_ISSET(idata.fd, &wset)){ 669 | idata.pending_write_f=FALSE; 670 | 671 | /* XXX: SEND PROBE PACKET */ 672 | 673 | if( sendto(idata.fd, sendbuff, nsendbuff, 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 674 | perror("iot-tddp: "); 675 | exit(EXIT_FAILURE); 676 | } 677 | 678 | 679 | if(gettimeofday(&lastprobe, NULL) == -1){ 680 | if(idata.verbose_f) 681 | perror("iot-tddp"); 682 | 683 | exit(EXIT_FAILURE); 684 | } 685 | 686 | retrans++; 687 | 688 | if(retrans >= idata.local_retrans) 689 | donesending_f= 1; 690 | 691 | } 692 | 693 | 694 | if(FD_ISSET(idata.fd, &eset)){ 695 | if(idata.verbose_f) 696 | puts("iot-tddp: Found exception on descriptor"); 697 | 698 | exit(EXIT_FAILURE); 699 | } 700 | if(FD_ISSET(idata.fd2, &eset)){ 701 | if(idata.verbose_f) 702 | puts("iot-tddp: Found exception on descriptor"); 703 | 704 | exit(EXIT_FAILURE); 705 | } 706 | } 707 | 708 | } 709 | 710 | exit(EXIT_SUCCESS); 711 | } 712 | 713 | 714 | 715 | 716 | /* 717 | * Function: match_strings() 718 | * 719 | * Checks whether one string "matches" within another string 720 | */ 721 | 722 | int match_strings(char *buscar, char *buffer){ 723 | unsigned int buscars, buffers; 724 | unsigned int i=0, j=0; 725 | 726 | buscars= Strnlen(buscar, MAX_IEEE_OUIS_LINE_SIZE); 727 | buffers= Strnlen(buffer, MAX_IEEE_OUIS_LINE_SIZE); 728 | 729 | if(buscars > buffers) 730 | return(0); 731 | 732 | while(i <= (buffers - buscars)){ 733 | j=0; 734 | 735 | while(j < buscars){ 736 | if(toupper((int) ((unsigned char)buscar[j])) != toupper((int) ((unsigned char)buffer[i+j]))) 737 | break; 738 | 739 | j++; 740 | } 741 | 742 | if(j >= buscars) 743 | return(1); 744 | 745 | i++; 746 | } 747 | 748 | return(0); 749 | } 750 | 751 | 752 | 753 | 754 | 755 | /* 756 | * Function: usage() 757 | * 758 | * Prints the syntax of the iot-tddp tool 759 | */ 760 | 761 | void usage(void){ 762 | puts("usage: iot-tddp (-L | -d) [-i INTERFACE] [-v] [-h]"); 763 | } 764 | 765 | 766 | /* 767 | * Function: print_help() 768 | * 769 | * Prints help information for the iot-tddp tool 770 | */ 771 | 772 | void print_help(void){ 773 | puts(SI6_TOOLKIT); 774 | puts( "iot-tddp: A tool to play with the TDDP protocol\n"); 775 | usage(); 776 | 777 | puts("\nOPTIONS:\n" 778 | " --interface, -i Network interface\n" 779 | " --dst-address, -d IP Destination Address\n" 780 | " --src-port, -o Transport Source Port\n" 781 | " --dst-port, -a Transport Destination Port\n" 782 | " --retrans, -x Number of retransmissions of each packet\n" 783 | " --timeout, -O Timeout in seconds (default: 1 second)\n" 784 | " --version, -V TDDP version\n" 785 | " --pktid, -I TDDP PktId\n" 786 | " --replyinfo, -r TDDP ReplyInfo\n" 787 | " --type, -T TDDP Type\n" 788 | " --subtype, -t TDDP SubType\n" 789 | " --code,-c TDDP Code\n" 790 | " --user, -u TP-Link device Username\n" 791 | " --password, -p TP-Link device Password\n" 792 | " --scan, -Z Scan for TP-Link devices\n" 793 | " --help, -h Print help for the iot-tddp tool\n" 794 | " --verbose, -v Be verbose\n" 795 | "\n" 796 | " Programmed by Fernando Gont for SI6 Networks \n" 797 | " Please send any bug reports to \n" 798 | ); 799 | } 800 | 801 | 802 | 803 | 804 | /* 805 | * Function: print_host_entries() 806 | * 807 | * Prints the IPv6 addresses (and optionally the Ethernet addresses) in a list 808 | */ 809 | 810 | int print_host_entries(struct host_list *hlist, unsigned char flag){ 811 | unsigned int i; 812 | 813 | for(i=0; i < (hlist->nhosts); i++){ 814 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 815 | if(verbose_f>1) 816 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 817 | 818 | return(-1); 819 | } 820 | 821 | if(flag == PRINT_ETHER_ADDR){ 822 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 823 | if(verbose_f>1) 824 | puts("ether_ntop(): Error converting address"); 825 | 826 | return(-1); 827 | } 828 | 829 | printf("%s @ %s\n", pv6addr, plinkaddr); 830 | } 831 | else 832 | printf("%s\n", pv6addr); 833 | } 834 | 835 | return 0; 836 | } 837 | 838 | 839 | 840 | /* 841 | * Function: print_unique_host_entries() 842 | * 843 | * Prints only one IPv6 address (and optionally the Ethernet addresses) per Ethernet 844 | * address in a list. 845 | */ 846 | 847 | int print_unique_host_entries(struct host_list *hlist, unsigned char flag){ 848 | unsigned int i, j, k; 849 | 850 | for(i=0; i < (hlist->nhosts); i++){ 851 | 852 | if(i){ 853 | for(j=0; j < i; j++){ 854 | for(k=0; k < ETH_ALEN; k++){ 855 | if((hlist->host[i])->ether.a[k] != (hlist->host[j])->ether.a[k]) 856 | break; 857 | } 858 | 859 | if(k == ETH_ALEN) 860 | break; 861 | } 862 | 863 | if(j < i) 864 | continue; 865 | } 866 | 867 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 868 | if(verbose_f>1) 869 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 870 | 871 | return(-1); 872 | } 873 | 874 | if(flag == PRINT_ETHER_ADDR){ 875 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 876 | if(verbose_f>1) 877 | puts("ether_ntop(): Error converting address"); 878 | 879 | return(-1); 880 | } 881 | 882 | printf("%s @ %s\n", pv6addr, plinkaddr); 883 | } 884 | else 885 | printf("%s\n", pv6addr); 886 | } 887 | 888 | return 0; 889 | } 890 | 891 | 892 | 893 | /* 894 | * Function: free_host_entries() 895 | * 896 | * Releases memory allocated for holding IPv6 addresses and Ethernet addresses 897 | */ 898 | 899 | void free_host_entries(struct host_list *hlist){ 900 | unsigned int i; 901 | 902 | for(i=0; i< hlist->nhosts; i++) 903 | free(hlist->host[i]); 904 | 905 | hlist->nhosts=0; /* Set the number of entries to 0, to reflect the released memory */ 906 | return; 907 | } 908 | 909 | 910 | 911 | 912 | 913 | void print_tddp_packet(void *ptr, unsigned int len){ 914 | struct tddp_hdr *tddp_hdr; 915 | unsigned int i; 916 | tddp_hdr= ptr; 917 | 918 | if(len < sizeof(struct tddp_hdr)) 919 | return; 920 | 921 | printf("Version: %02x Type: %02x Subtype: %02x Code: %02x ReplyInfo: %02x PktLength: %08x"\ 922 | " PktId: %04x\nMD5 Digest: ",\ 923 | tddp_hdr->version, tddp_hdr->type, tddp_hdr->subtype, tddp_hdr->code, tddp_hdr->replyinfo, \ 924 | ntohl(tddp_hdr->pktlength), ntohs(tddp_hdr->pktid)); 925 | 926 | for(i=0; i<16; i++){ 927 | printf("%02x", tddp_hdr->md5_digest[i]); 928 | } 929 | 930 | puts(""); 931 | puts("Payload:"); 932 | dump_text((char *) ptr + sizeof(struct tddp_hdr), len- sizeof(struct tddp_hdr)); 933 | } 934 | 935 | -------------------------------------------------------------------------------- /tools/iot-tddp.c~: -------------------------------------------------------------------------------- 1 | /* 2 | * iot-scan: An IoT Scanning Tool 3 | * 4 | * Copyright (C) 2017 Fernando Gont 5 | * 6 | * Programmed by Fernando Gont for SI6 Networks 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * Build with: make iot-scan 22 | * 23 | * It requires that the libpcap library be installed on your system. 24 | * 25 | * Please send any bug reports to Fernando Gont 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | 56 | #include "iot-tddp.h" 57 | #include "iot-toolkit.h" 58 | #include "libiot.h" 59 | 60 | /* #define DEBUG */ 61 | 62 | /* Function prototypes */ 63 | void init_packet_data(struct iface_data *); 64 | void free_host_entries(struct host_list *); 65 | int host_scan_local(pcap_t *, struct iface_data *, struct in6_addr *, unsigned char, \ 66 | struct host_entry *); 67 | void print_help(void); 68 | int print_host_entries(struct host_list *, unsigned char); 69 | void local_sig_alarm(int); 70 | void usage(void); 71 | int process_config_file(const char *); 72 | 73 | /* Used for multiscan */ 74 | struct host_list host_local, host_global, host_candidate; 75 | struct host_entry *host_locals[MAX_IPV6_ENTRIES], *host_globals[MAX_IPV6_ENTRIES]; 76 | struct host_entry *host_candidates[MAX_IPV6_ENTRIES]; 77 | 78 | /* Used for router discovery */ 79 | struct iface_data idata; 80 | 81 | /* Variables used for learning the default router */ 82 | struct ether_addr router_ether, rs_ether; 83 | struct in6_addr router_ipv6, rs_ipv6; 84 | 85 | struct in6_addr randprefix; 86 | unsigned char randpreflen; 87 | 88 | bpf_u_int32 my_netmask; 89 | bpf_u_int32 my_ip; 90 | struct bpf_program pcap_filter; 91 | char dev[64], errbuf[PCAP_ERRBUF_SIZE]; 92 | unsigned char buffer[BUFFER_SIZE], buffrh[MIN_IPV6_HLEN + MIN_TCP_HLEN]; 93 | char readbuff[BUFFER_SIZE], sendbuff[BUFFER_SIZE]; 94 | ssize_t nreadbuff, nsendbuff; 95 | char line[LINE_BUFFER_SIZE]; 96 | unsigned char *v6buffer, *ptr, *startofprefixes; 97 | char *pref; 98 | 99 | struct ether_header *ethernet; 100 | unsigned int ndst=0; 101 | 102 | char *lasts, *rpref; 103 | char *charptr; 104 | 105 | size_t nw; 106 | unsigned long ul_res, ul_val; 107 | unsigned int i, j, startrand; 108 | unsigned int skip; 109 | unsigned char dstpreflen; 110 | 111 | uint16_t mask; 112 | 113 | char plinkaddr[ETHER_ADDR_PLEN], pv4addr[INET_ADDRSTRLEN]; 114 | char pv6addr[INET6_ADDRSTRLEN]; 115 | unsigned char verbose_f=FALSE; 116 | unsigned char dstaddr_f=FALSE, timestamps_f=FALSE, scan_local_f=FALSE; 117 | 118 | 119 | 120 | unsigned char dst_f=FALSE, end_f=FALSE, endpscan_f=FALSE; 121 | unsigned char donesending_f=FALSE; 122 | uint16_t srcport, dstport; 123 | uint32_t scan_type; 124 | char scan_type_f=FALSE; 125 | unsigned long pktinterval, rate; 126 | unsigned int packetsize; 127 | 128 | struct prefixv4_entry prefix; 129 | 130 | char *charstart, *charend, *lastcolon; 131 | unsigned int nsleep; 132 | int sel; 133 | fd_set srset, swset, seset, rset, wset, eset; 134 | struct timeval curtime, pcurtime, lastprobe; 135 | struct tm pcurtimetm; 136 | unsigned int retrans=0; 137 | 138 | int main(int argc, char **argv){ 139 | extern char *optarg; 140 | int r; 141 | struct addrinfo hints, *res, *aiptr; 142 | struct target_ipv6 target; 143 | struct timeval timeout; 144 | void *voidptr; 145 | const int on=1; 146 | struct sockaddr_in sockaddr_in, sockaddr_from, sockaddr_to; 147 | socklen_t sockaddrfrom_len; 148 | struct tddp_hdr *tddp_hdr; 149 | unsigned int npayload=0; 150 | /* 151 | ## Packet Type 152 | # 0x01 SET_USR_CFG - set configuration information 153 | # 0x02 GET_SYS_INF - get configuration information 154 | # 0x03 CMD_SPE_OPR - special configuration commands 155 | # 0x04 HEART_BEAT - the heartbeat package 156 | tddp_type = "03" 157 | 158 | ## Code Request Type 159 | # 0x01 TDDP_REQUEST 160 | # 0x02 TDDP_REPLY 161 | tddp_code = "01" 162 | 163 | ## Reply Info Status 164 | # 0x00 REPLY_OK 165 | # 0x02 ? 166 | # 0x03 ? 167 | # 0x09 REPLY_ERROR 168 | # 0xFF ? 169 | tddp_reply = "00" 170 | 171 | ## Packet Length (not including header) 172 | # 4 bytes 173 | tddp_length = "00000000" 174 | 175 | ## Packet ID 176 | # 2 bytes 177 | # supposed to be incremented +1 for each packet 178 | tddp_id = "0001" 179 | 180 | # Subtype for CMD_SPE_OPR (Special Operations Command) 181 | # Set to 0x00 for SET_USR_CFG and GET_SYS_INF 182 | # 183 | # Subtypes described in patent application, hex value unknown: 184 | # CMD_SYS_OPR Router system operation, including: init, save, reboot, reset, clr dos 185 | # CMD_AUTO_TEST MAC for writing operation, the user replies CMD_SYS_INIT broadcast packet 186 | # CMD_CONFIG_MAC Factory settings MAC operations 187 | # CMD_CANCEL_TEST Cancel automatic test, stop receiving broadcast packets 188 | # CMD_GET_PROD_ID Get product ID 189 | # CMD_SYS_INIT Initialize a router 190 | # CMD_CONFIG_PIN Router PIN code 191 | # 192 | # Subtypes that seem to work for a HS-110 Smart Plug: 193 | # 0x0A returns "ABCD0110" 194 | # 0x12 returns the deviceID 195 | # 0x14 returns the hwID 196 | # 0x06 changes MAC 197 | # 0x13 changes deviceID 198 | # 0x15 changes deviceID 199 | # 200 | # Subtypes that seem to work for an Archer C9 Router: 201 | # 0x0E returns physical status of WAN link: 202 | # wan_ph_link 1 0 = disconnected 203 | # wan_ph_link 1 1 = connected 204 | # 0x0F returns logical status of WAN link: wan_logic_link 1 0 205 | # 0x0A returns \x00\x09\x00\x01\x00\x00\x00\x00 206 | # 0x15 returns \x01\x00\x00\x00\x00\x00\x00\x00 207 | # 0x18 returns 1 208 | */ 209 | 210 | char username_admin[]="admin"; 211 | char password_admin[]="admin"; 212 | char *username; 213 | char *password; 214 | unsigned int nusername; 215 | unsigned int npassword; 216 | char preparekey[BUFFER_SIZE]; 217 | char keydigest[MD5_DIGEST_LENGTH]; 218 | DES_cblock des_key[8]; 219 | DES_key_schedule key; 220 | /* 221 | DES_cblock ciphertext; 222 | DES_cblock buf; 223 | */ 224 | uint8_t tddp_version=2; 225 | 226 | /* 227 | # 0x01 SET_USR_CFG - set configuration information 228 | # 0x02 GET_SYS_INF - get configuration information 229 | # 0x03 CMD_SPE_OPR - special configuration commands 230 | # 0x04 HEART_BEAT - the heartbeat package 231 | */ 232 | uint8_t tddp_type= 0x03; /* GETSYSINF*/ 233 | 234 | /* 235 | ## Code Request Type 236 | # 0x01 TDDP_REQUEST 237 | # 0x02 TDDP_REPLY 238 | tddp_code = "01" 239 | */ 240 | uint8_t tddp_code=0x01; 241 | 242 | /* 243 | ## Reply Info Status 244 | # 0x00 REPLY_OK 245 | # 0x02 ? 246 | # 0x03 ? 247 | # 0x09 REPLY_ERROR 248 | # 0xFF ? 249 | tddp_reply = "00" 250 | */ 251 | uint8_t tddp_replyinfo= 0x00; 252 | uint16_t tddp_pktid= 0x0020; 253 | uint8_t tddp_subtype= 0x00; 254 | MD5_CTX mdContext; 255 | 256 | static struct option longopts[] = { 257 | {"interface", required_argument, 0, 'i'}, 258 | {"pktid", required_argument, 0, 'I'}, 259 | {"code", required_argument, 0, 'c'}, 260 | {"dst-address", required_argument, 0, 'd'}, 261 | {"local-scan", no_argument, 0, 'L'}, 262 | {"retrans", required_argument, 0, 'x'}, 263 | {"timeout", required_argument, 0, 'O'}, 264 | {"subtype", required_argument, 0, 't'}, 265 | {"type", required_argument, 0, 'T'}, 266 | {"user", required_argument, 0, 'u'}, 267 | {"src-port", required_argument, 0, 'o'}, 268 | {"dst-port", required_argument, 0, 'a'}, 269 | {"password", required_argument, 0, 'p'}, 270 | {"replyinfo", required_argument, 0, 'r'}, 271 | {"verbose", no_argument, 0, 'v'}, 272 | {"version", required_argument, 0, 'V'}, 273 | {"help", no_argument, 0, 'h'}, 274 | {0, 0, 0, 0 } 275 | }; 276 | 277 | char shortopts[]= "i:I:c:d:Lx:O:t:T:u:o:a:p:r:vV:h"; 278 | 279 | char option; 280 | 281 | if(argc<=1){ 282 | usage(); 283 | exit(EXIT_FAILURE); 284 | } 285 | 286 | srandom(time(NULL)); 287 | 288 | init_iface_data(&idata); 289 | 290 | /* Set defaults */ 291 | username= username_admin; 292 | password= password_admin; 293 | tddp_type= 0x03; /* GETSYSINF*/ 294 | tddp_code=0x01; 295 | tddp_replyinfo= 0x00; 296 | tddp_pktid= 0x0020; 297 | tddp_subtype= 0x00; 298 | 299 | 300 | 301 | while((r=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { 302 | option= r; 303 | 304 | switch(option) { 305 | case 'i': /* Interface */ 306 | strncpy(idata.iface, optarg, IFACE_LENGTH-1); 307 | idata.iface[IFACE_LENGTH-1]=0; 308 | idata.ifindex= if_nametoindex(idata.iface); 309 | idata.iface_f=TRUE; 310 | break; 311 | 312 | case 'I': 313 | tddp_pktid=atoi(optarg); 314 | break; 315 | 316 | case 'c': 317 | tddp_code=atoi(optarg); 318 | break; 319 | 320 | case 't': 321 | tddp_subtype=atoi(optarg); 322 | break; 323 | 324 | case 'T': 325 | tddp_type=atoi(optarg); 326 | break; 327 | 328 | case 'V': 329 | tddp_version=atoi(optarg); 330 | break; 331 | 332 | case 'u': 333 | username= optarg; 334 | break; 335 | 336 | case 'p': 337 | password= optarg; 338 | break; 339 | 340 | case 'r': 341 | tddp_replyinfo=atoi(optarg); 342 | break; 343 | 344 | case 'd': /* IPv6 Destination Address/Prefix */ 345 | /* The '-d' option contains a domain name */ 346 | if((charptr = strtok_r(optarg, "/", &lasts)) == NULL){ 347 | puts("Error in Destination Address"); 348 | exit(EXIT_FAILURE); 349 | } 350 | 351 | strncpy(target.name, charptr, NI_MAXHOST); 352 | target.name[NI_MAXHOST-1]=0; 353 | 354 | if((charptr = strtok_r(NULL, " ", &lasts)) != NULL){ 355 | prefix.len = atoi(charptr); 356 | 357 | if(prefix.len > 32){ 358 | puts("Prefix length error in IP Destination Address"); 359 | exit(EXIT_FAILURE); 360 | } 361 | } 362 | else{ 363 | prefix.len= 32; 364 | } 365 | 366 | memset(&hints, 0, sizeof(hints)); 367 | hints.ai_family= AF_INET; 368 | hints.ai_canonname = NULL; 369 | hints.ai_addr = NULL; 370 | hints.ai_next = NULL; 371 | hints.ai_socktype= SOCK_DGRAM; 372 | 373 | if( (target.res = getaddrinfo(target.name, NULL, &hints, &res)) != 0){ 374 | printf("Unknown Destination '%s': %s\n", target.name, gai_strerror(target.res)); 375 | exit(1); 376 | } 377 | 378 | for(aiptr=res; aiptr != NULL; aiptr=aiptr->ai_next){ 379 | if(aiptr->ai_family != AF_INET) 380 | continue; 381 | 382 | if(aiptr->ai_addrlen != sizeof(struct sockaddr_in)) 383 | continue; 384 | 385 | if(aiptr->ai_addr == NULL) 386 | continue; 387 | 388 | prefix.ip= ( (struct sockaddr_in *)aiptr->ai_addr)->sin_addr; 389 | } 390 | 391 | freeaddrinfo(res); 392 | 393 | idata.dstaddr= prefix.ip; 394 | idata.dstaddr_f= TRUE; 395 | dst_f=TRUE; 396 | break; 397 | 398 | case 'L': 399 | scan_local_f=TRUE; 400 | break; 401 | 402 | case 'x': 403 | idata.local_retrans=atoi(optarg); 404 | break; 405 | 406 | case 'o': /* UDP Source Port */ 407 | idata.srcport= atoi(optarg); 408 | idata.srcport_f= 1; 409 | break; 410 | 411 | case 'a': /* UDP Destination Port */ 412 | idata.dstport= atoi(optarg); 413 | idata.dstport_f= 1; 414 | break; 415 | 416 | case 'O': 417 | idata.local_timeout=atoi(optarg); 418 | break; 419 | 420 | case 'v': /* Be verbose */ 421 | idata.verbose_f++; 422 | break; 423 | 424 | case 'h': /* Help */ 425 | print_help(); 426 | exit(EXIT_FAILURE); 427 | break; 428 | 429 | default: 430 | usage(); 431 | exit(EXIT_FAILURE); 432 | break; 433 | 434 | } /* switch */ 435 | } /* while(getopt) */ 436 | 437 | 438 | nusername= Strnlen(username, BUFFER_SIZE); 439 | npassword= Strnlen(password, BUFFER_SIZE); 440 | 441 | if( (nusername+npassword+2) > BUFFER_SIZE){ 442 | puts("Username/password too long"); 443 | exit(EXIT_FAILURE); 444 | } 445 | 446 | strncpy(preparekey, username, nusername); 447 | strncpy( (char *)preparekey + nusername, password, npassword); 448 | /* Preparekey now contains the concatenated username and assword */ 449 | 450 | MD5_Init(&mdContext); 451 | MD5_Update(&mdContext, preparekey, nusername+npassword); 452 | MD5_Final((unsigned char *)keydigest, &mdContext); 453 | 454 | memcpy(des_key, keydigest, 8); 455 | 456 | 457 | /* 458 | XXX: This is rather ugly, but some local functions need to check for verbosity, and it was not warranted 459 | to pass &idata as an argument 460 | */ 461 | verbose_f= idata.verbose_f; 462 | 463 | if(geteuid()){ 464 | puts("iot-scan needs superuser privileges to run"); 465 | exit(EXIT_FAILURE); 466 | } 467 | 468 | if(scan_local_f && !idata.iface_f){ 469 | /* XXX This should later allow to just specify local scan and automatically choose an interface */ 470 | puts("Must specify the network interface with the -i option when a local scan is selected"); 471 | /* exit(EXIT_FAILURE); */ 472 | } 473 | 474 | if(!dst_f && !scan_local_f){ 475 | if(idata.verbose_f) 476 | puts("Must specify either a destination prefix ('-d'), or a local scan ('-L')"); 477 | 478 | exit(EXIT_FAILURE); 479 | } 480 | 481 | release_privileges(); 482 | 483 | if(get_local_addrs(&idata) == FAILURE){ 484 | puts("Error obtaining list of local interfaces and addresses"); 485 | exit(EXIT_FAILURE); 486 | } 487 | 488 | puts("Antes de chequear que hago"); 489 | 490 | if(scan_local_f){ 491 | /* If an interface was specified, we select an IPv4 address from such interface */ 492 | if(idata.iface_f){ 493 | if( (voidptr=find_v4addr_for_iface(&(idata.iflist), idata.iface)) == NULL){ 494 | printf("No IPv4 address for interface %s\n", idata.iface); 495 | exit(EXIT_FAILURE); 496 | } 497 | 498 | idata.srcaddr= *((struct in_addr *) voidptr); 499 | } 500 | else{ 501 | if( (voidptr=find_v4addr(&(idata.iflist))) == NULL){ 502 | puts("No IPv4 address available on local host"); 503 | exit(EXIT_FAILURE); 504 | } 505 | 506 | idata.srcaddr= *((struct in_addr *)voidptr); 507 | } 508 | 509 | if( (idata.fd=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 510 | puts("Could not create socket"); 511 | exit(EXIT_FAILURE); 512 | } 513 | 514 | if( setsockopt(idata.fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1){ 515 | puts("Error while setting SO_BROADCAST socket option"); 516 | exit(EXIT_FAILURE); 517 | } 518 | 519 | memset(&sockaddr_in, 0, sizeof(sockaddr_in)); 520 | sockaddr_in.sin_family= AF_INET; 521 | sockaddr_in.sin_port= 0; /* Allow Sockets API to set an ephemeral port */ 522 | sockaddr_in.sin_addr= idata.srcaddr; 523 | 524 | if(bind(idata.fd, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1){ 525 | puts("Error bind()ing socket to local address"); 526 | exit(EXIT_FAILURE); 527 | } 528 | 529 | /* Second (receive) socket */ 530 | if( (idata.fd2=socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 531 | puts("Could not create socket"); 532 | exit(EXIT_FAILURE); 533 | } 534 | 535 | memset(&sockaddr_in, 0, sizeof(sockaddr_in)); 536 | sockaddr_in.sin_family= AF_INET; 537 | sockaddr_in.sin_port= htons(TDDP_RECEIVE_PORT); /* Allow Sockets API to set an ephemeral port */ 538 | sockaddr_in.sin_addr= idata.srcaddr; 539 | 540 | if(bind(idata.fd2, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1){ 541 | puts("Error bind()ing socket to local address"); 542 | exit(EXIT_FAILURE); 543 | } 544 | 545 | memset(&sockaddr_to, 0, sizeof(sockaddr_to)); 546 | sockaddr_to.sin_family= AF_INET; 547 | sockaddr_to.sin_port= htons(TDDP_SERVICE_PORT); 548 | sockaddr_to.sin_addr= idata.dstaddr; 549 | 550 | memset(&sockaddr_from, 0, sizeof(sockaddr_from)); 551 | sockaddr_from.sin_family= AF_INET; 552 | sockaddrfrom_len=sizeof(sockaddr_from); 553 | tddp_hdr= (struct tddp_hdr *) sendbuff; 554 | memset(tddp_hdr, 0, sizeof(struct tddp_hdr)); 555 | 556 | tddp_hdr->version= tddp_version; 557 | tddp_hdr->type= tddp_type; 558 | tddp_hdr->code= tddp_code; 559 | tddp_hdr->replyinfo= tddp_replyinfo; 560 | tddp_hdr->pktid= tddp_pktid; 561 | tddp_hdr->subtype= tddp_subtype; 562 | tddp_hdr->res= 0x00; 563 | 564 | charptr= (char *) (sendbuff + sizeof(struct tddp_hdr));; 565 | /* here we should insert any data */ 566 | npayload= charptr- sendbuff - sizeof(struct tddp_hdr); 567 | 568 | /* XXX check bounds */ 569 | for(i=0; i < (npayload%8); i++){ 570 | *charptr= 0x00; 571 | charptr++; 572 | } 573 | 574 | 575 | nsendbuff= charptr- sendbuff; 576 | npayload= nsendbuff - sizeof(struct tddp_hdr); 577 | tddp_hdr->pktlength= htonl( (uint32_t)npayload); 578 | 579 | if(npayload){ 580 | ERR_clear_error(); 581 | 582 | if(DES_set_key(des_key, &key) < 0){ 583 | puts("Error setting up DES key"); 584 | exit(EXIT_FAILURE); 585 | } 586 | 587 | for(i=0; i< (npayload/8); i++){ 588 | DES_ecb_encrypt( (DES_cblock *) charptr, (DES_cblock *) charptr, &key, 1); 589 | charptr= charptr+8; 590 | } 591 | } 592 | 593 | /* Now compute MD5 checksum */ 594 | MD5_Init(&mdContext); 595 | MD5_Update(&mdContext, sendbuff, nsendbuff); 596 | MD5_Final (tddp_hdr->md5_digest ,&mdContext); 597 | puts("This is what I'm going to send"); 598 | print_tddp_packet(sendbuff, nsendbuff); 599 | 600 | if(!idata.dstaddr_f){ 601 | puts("Must specify destination address"); 602 | exit(EXIT_FAILURE); 603 | } 604 | 605 | 606 | FD_ZERO(&srset); 607 | FD_ZERO(&swset); 608 | FD_ZERO(&seset); 609 | 610 | FD_SET(idata.fd, &swset); 611 | FD_SET(idata.fd, &srset); 612 | FD_SET(idata.fd2, &srset); 613 | FD_SET(idata.fd, &seset); 614 | FD_SET(idata.fd2, &seset); 615 | 616 | lastprobe.tv_sec= 0; 617 | lastprobe.tv_usec=0; 618 | idata.pending_write_f=TRUE; 619 | 620 | /* The end_f flag is set after the last probe has been sent and a timeout period has elapsed. 621 | That is, we give responses enough time to come back 622 | */ 623 | while(!end_f){ 624 | rset= srset; 625 | wset= swset; 626 | eset= seset; 627 | 628 | if(!donesending_f){ 629 | /* This is the retransmission timer */ 630 | timeout.tv_sec= 1; 631 | timeout.tv_usec= 0; 632 | } 633 | else{ 634 | /* XXX: This should use the parameter from command line */ 635 | timeout.tv_sec= idata.local_timeout; 636 | timeout.tv_usec=0; 637 | } 638 | 639 | /* 640 | Check for readability and exceptions. We only check for writeability if there is pending data 641 | to send. 642 | */ 643 | if((sel=select(idata.fd2+1, &rset, (idata.pending_write_f?&wset:NULL), &eset, &timeout)) == -1){ 644 | if(errno == EINTR){ 645 | continue; 646 | } 647 | else{ 648 | perror("iot-scan:"); 649 | exit(EXIT_FAILURE); 650 | } 651 | } 652 | 653 | if(gettimeofday(&curtime, NULL) == -1){ 654 | if(idata.verbose_f) 655 | perror("iot-scan"); 656 | 657 | exit(EXIT_FAILURE); 658 | } 659 | 660 | /* Check whether we have finished probing all targets */ 661 | if(donesending_f){ 662 | /* 663 | Just wait for SELECT_TIMEOUT seconds for any incoming responses. 664 | */ 665 | 666 | if(is_time_elapsed(&curtime, &lastprobe, idata.local_timeout * 1000000)){ 667 | end_f=TRUE; 668 | } 669 | } 670 | 671 | 672 | if(sel && FD_ISSET(idata.fd2, &rset)){ 673 | puts("Reading from socket"); 674 | /* XXX: Process response packet */ 675 | 676 | if( (nreadbuff = recvfrom(idata.fd2, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 677 | perror("iot-scan: "); 678 | exit(EXIT_FAILURE); 679 | } 680 | 681 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 682 | perror("iot-scan: "); 683 | exit(EXIT_FAILURE); 684 | } 685 | 686 | printf("Read %u bytes from %s\n", (unsigned int)nreadbuff, pv4addr); 687 | print_tddp_packet(readbuff, nreadbuff); 688 | } 689 | 690 | if(sel && FD_ISSET(idata.fd, &rset)){ 691 | puts("Reading from socket"); 692 | /* XXX: Process response packet */ 693 | 694 | if( (nreadbuff = recvfrom(idata.fd, readbuff, sizeof(readbuff), 0, (struct sockaddr *)&sockaddr_from, &sockaddrfrom_len)) == -1){ 695 | perror("iot-scan: "); 696 | exit(EXIT_FAILURE); 697 | } 698 | 699 | if(inet_ntop(AF_INET, &(sockaddr_from.sin_addr), pv4addr, sizeof(pv4addr)) == NULL){ 700 | perror("iot-scan: "); 701 | exit(EXIT_FAILURE); 702 | } 703 | 704 | /* There's data to be desencrypted */ 705 | if(nreadbuff> sizeof(struct tddp_hdr)){ 706 | for(i=0; i< ((nreadbuff-sizeof(struct tddp_hdr))/8); i++){ 707 | DES_ecb_encrypt( (DES_cblock *)(readbuff+ sizeof(struct tddp_hdr) + i * 8), \ 708 | (DES_cblock *)(readbuff+ sizeof(struct tddp_hdr) + i * 8), &key, 0); 709 | } 710 | } 711 | 712 | printf("Read %u bytes from %s\n", (unsigned int)nreadbuff, pv4addr); 713 | print_tddp_packet(readbuff, nreadbuff); 714 | } 715 | 716 | 717 | if(!donesending_f && !idata.pending_write_f && is_time_elapsed(&curtime, &lastprobe, 1 * 1000000)){ 718 | idata.pending_write_f=TRUE; 719 | continue; 720 | } 721 | 722 | if(!donesending_f && idata.pending_write_f && FD_ISSET(idata.fd, &wset)){ 723 | puts("Going to write"); 724 | idata.pending_write_f=FALSE; 725 | 726 | /* XXX: SEND PROBE PACKET */ 727 | if( sendto(idata.fd, sendbuff, nsendbuff, 0, (struct sockaddr *) &sockaddr_to, sizeof(sockaddr_to)) == -1){ 728 | perror("iot-scan: "); 729 | exit(EXIT_FAILURE); 730 | } 731 | 732 | if(gettimeofday(&lastprobe, NULL) == -1){ 733 | if(idata.verbose_f) 734 | perror("iot-scan"); 735 | 736 | exit(EXIT_FAILURE); 737 | } 738 | 739 | retrans++; 740 | 741 | if(retrans >= idata.local_retrans) 742 | donesending_f= 1; 743 | 744 | } 745 | 746 | 747 | if(FD_ISSET(idata.fd, &eset)){ 748 | if(idata.verbose_f) 749 | puts("iot-scaner: Found exception on descriptor"); 750 | 751 | exit(EXIT_FAILURE); 752 | } 753 | if(FD_ISSET(idata.fd2, &eset)){ 754 | if(idata.verbose_f) 755 | puts("iot-scaner: Found exception on descriptor"); 756 | 757 | exit(EXIT_FAILURE); 758 | } 759 | } 760 | 761 | } 762 | 763 | exit(EXIT_SUCCESS); 764 | } 765 | 766 | 767 | 768 | 769 | /* 770 | * Function: match_strings() 771 | * 772 | * Checks whether one string "matches" within another string 773 | */ 774 | 775 | int match_strings(char *buscar, char *buffer){ 776 | unsigned int buscars, buffers; 777 | unsigned int i=0, j=0; 778 | 779 | buscars= Strnlen(buscar, MAX_IEEE_OUIS_LINE_SIZE); 780 | buffers= Strnlen(buffer, MAX_IEEE_OUIS_LINE_SIZE); 781 | 782 | if(buscars > buffers) 783 | return(0); 784 | 785 | while(i <= (buffers - buscars)){ 786 | j=0; 787 | 788 | while(j < buscars){ 789 | if(toupper((int) ((unsigned char)buscar[j])) != toupper((int) ((unsigned char)buffer[i+j]))) 790 | break; 791 | 792 | j++; 793 | } 794 | 795 | if(j >= buscars) 796 | return(1); 797 | 798 | i++; 799 | } 800 | 801 | return(0); 802 | } 803 | 804 | 805 | 806 | 807 | 808 | /* 809 | * Function: usage() 810 | * 811 | * Prints the syntax of the iot-scan tool 812 | */ 813 | 814 | void usage(void){ 815 | puts("usage: iot-scan (-L | -d) [-i INTERFACE] [-v] [-h]"); 816 | } 817 | 818 | 819 | /* 820 | * Function: print_help() 821 | * 822 | * Prints help information for the iot-scan tool 823 | */ 824 | 825 | void print_help(void){ 826 | puts(SI6_TOOLKIT); 827 | puts( "iot-scan: An IoT scanning tool\n"); 828 | usage(); 829 | 830 | puts("\nOPTIONS:\n" 831 | " --interface, -i Network interface\n" 832 | " --dst-address, -d IPv6 Destination Range or Prefix\n" 833 | " --retrans, -x Number of retransmissions of each probe\n" 834 | " --timeout, -O Timeout in seconds (default: 1 second)\n" 835 | " --local-scan, -L Scan the local subnet\n" 836 | " --help, -h Print help for the iot-scan tool\n" 837 | " --verbose, -v Be verbose\n" 838 | "\n" 839 | " Programmed by Fernando Gont for SI6 Networks \n" 840 | " Please send any bug reports to \n" 841 | ); 842 | } 843 | 844 | 845 | 846 | /* 847 | * Function: print_host_entries() 848 | * 849 | * Prints the IPv6 addresses (and optionally the Ethernet addresses) in a list 850 | */ 851 | 852 | int print_host_entries(struct host_list *hlist, unsigned char flag){ 853 | unsigned int i; 854 | 855 | for(i=0; i < (hlist->nhosts); i++){ 856 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 857 | if(verbose_f>1) 858 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 859 | 860 | return(-1); 861 | } 862 | 863 | if(flag == PRINT_ETHER_ADDR){ 864 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 865 | if(verbose_f>1) 866 | puts("ether_ntop(): Error converting address"); 867 | 868 | return(-1); 869 | } 870 | 871 | printf("%s @ %s\n", pv6addr, plinkaddr); 872 | } 873 | else 874 | printf("%s\n", pv6addr); 875 | } 876 | 877 | return 0; 878 | } 879 | 880 | 881 | 882 | /* 883 | * Function: print_unique_host_entries() 884 | * 885 | * Prints only one IPv6 address (and optionally the Ethernet addresses) per Ethernet 886 | * address in a list. 887 | */ 888 | 889 | int print_unique_host_entries(struct host_list *hlist, unsigned char flag){ 890 | unsigned int i, j, k; 891 | 892 | for(i=0; i < (hlist->nhosts); i++){ 893 | 894 | if(i){ 895 | for(j=0; j < i; j++){ 896 | for(k=0; k < ETH_ALEN; k++){ 897 | if((hlist->host[i])->ether.a[k] != (hlist->host[j])->ether.a[k]) 898 | break; 899 | } 900 | 901 | if(k == ETH_ALEN) 902 | break; 903 | } 904 | 905 | if(j < i) 906 | continue; 907 | } 908 | 909 | if(inet_ntop(AF_INET6, &((hlist->host[i])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 910 | if(verbose_f>1) 911 | puts("inet_ntop(): Error converting IPv6 address to presentation format"); 912 | 913 | return(-1); 914 | } 915 | 916 | if(flag == PRINT_ETHER_ADDR){ 917 | if(ether_ntop( &((hlist->host[i])->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 918 | if(verbose_f>1) 919 | puts("ether_ntop(): Error converting address"); 920 | 921 | return(-1); 922 | } 923 | 924 | printf("%s @ %s\n", pv6addr, plinkaddr); 925 | } 926 | else 927 | printf("%s\n", pv6addr); 928 | } 929 | 930 | return 0; 931 | } 932 | 933 | 934 | 935 | /* 936 | * Function: free_host_entries() 937 | * 938 | * Releases memory allocated for holding IPv6 addresses and Ethernet addresses 939 | */ 940 | 941 | void free_host_entries(struct host_list *hlist){ 942 | unsigned int i; 943 | 944 | for(i=0; i< hlist->nhosts; i++) 945 | free(hlist->host[i]); 946 | 947 | hlist->nhosts=0; /* Set the number of entries to 0, to reflect the released memory */ 948 | return; 949 | } 950 | 951 | 952 | 953 | 954 | 955 | void print_tddp_packet(void *ptr, unsigned int len){ 956 | struct tddp_hdr *tddp_hdr; 957 | unsigned int i; 958 | tddp_hdr= ptr; 959 | 960 | if(len < sizeof(struct tddp_hdr)) 961 | return; 962 | 963 | printf("Version: %02x Type: %02x Subtype: %02x Code: %02x ReplyInfo: %02x PktLength: %08x"\ 964 | " PktId: %04x\nMD5 Digest: ",\ 965 | tddp_hdr->version, tddp_hdr->type, tddp_hdr->subtype, tddp_hdr->code, tddp_hdr->replyinfo, \ 966 | ntohl(tddp_hdr->pktlength), ntohs(tddp_hdr->pktid)); 967 | 968 | for(i=0; i<16; i++){ 969 | printf("%02x", tddp_hdr->md5_digest[i]); 970 | } 971 | 972 | puts(""); 973 | puts("Payload:"); 974 | dump_text((char *) ptr + sizeof(struct tddp_hdr), len- sizeof(struct tddp_hdr)); 975 | } 976 | 977 | -------------------------------------------------------------------------------- /tools/iot-tddp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the iot-scanner tool 3 | * 4 | */ 5 | 6 | #define BUFFER_SIZE 65556 7 | 8 | /* Constants used with the multi_scan_local() function */ 9 | #define PROBE_ICMP6_ECHO 1 10 | #define PROBE_UNREC_OPT 2 11 | #define PROBE_TCP 3 12 | #define LOCAL_SRC 1 13 | #define GLOBAL_SRC 2 14 | 15 | #define ICMPV6_ECHO_PAYLOAD_SIZE 56 16 | #define MAX_IPV6_ENTRIES 65000 17 | 18 | /* Constant for the host-scanning functions */ 19 | #define PRINT_ETHER_ADDR 1 20 | #define NOT_PRINT_ETHER_ADDR 0 21 | 22 | #define VALID_MAPPING 1 23 | #define INVALID_MAPPING 0 24 | 25 | 26 | /* Remote scans */ 27 | #define LOW_BYTE_1ST_WORD_UPPER 0x1500 28 | #define LOW_BYTE_2ND_WORD_UPPER 0x0100 29 | #define EMBEDDED_PORT_2ND_WORD 5 30 | #define MAX_IEEE_OUIS_LINE_SIZE 160 31 | #define OUI_HEX_STRING_SIZE 5 32 | #define MAX_IEEE_OUIS 1000 33 | #define MAX_SCAN_ENTRIES 65535 34 | #define MAX_PORT_ENTRIES 65536 35 | #define MAX_PREF_ENTRIES MAX_SCAN_ENTRIES 36 | #define SELECT_TIMEOUT 4 37 | #define PSCAN_TIMEOUT 1 38 | #define MAX_RANGE_STR_LEN 79 39 | #define MIN_INC_RANGE 1000 40 | /* #define MAX_DESTNATIONS 65535 */ 41 | #define MAX_IID_ENTRIES 65535 42 | 43 | #define ND_RETRIES 0 44 | 45 | /* Constants for config file processing */ 46 | #define MAX_LINE_SIZE 250 47 | #define MAX_VAR_NAME_LEN 100 48 | #define MAX_FILENAME_SIZE 250 49 | 50 | 51 | union my6_addr{ 52 | uint8_t s6addr[16]; 53 | uint16_t s6addr16[8]; 54 | uint32_t s6addr32[4]; 55 | struct in6_addr in6_addr; 56 | }; 57 | 58 | 59 | #define MAX_PORTS_LINE_SIZE 80 60 | 61 | 62 | 63 | /* Constants for port scan results */ 64 | 65 | #define PORT_FILTERED 1 66 | #define PORT_OPEN 2 67 | #define PORT_CLOSED 4 68 | #define PORT_ACT_FILT 8 69 | 70 | 71 | #define DEFAULT_MIN_PORT 0 72 | #define DEFAULT_MAX_PORT 65535 73 | #define MAX_PORT_RANGE 65536 74 | #define IPPROTO_ALL 0xf1 /* Fake number to indicate both TCP and UDP */ 75 | 76 | #define SET_RELAY_ON 1 77 | #define SET_RELAY_OFF 2 78 | 79 | /* Constants for printing the scanning results */ 80 | 81 | /* Steps into which results will be printed */ 82 | /*#define MAX_STEPS 20*/ 83 | #define MAX_COMMAND_LENGTH 500 84 | 85 | /* 86 | 0 1 2 3 87 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 88 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 89 | | Ver | Type | Code | ReplyInfo | 90 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 91 | | PktLength | 92 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 93 | | PktID | SubType | Reserve | 94 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 95 | | MD5 Digest[0-3] | 96 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 97 | | MD5 Digest[4-7] | 98 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 99 | | MD5 Digest[8-11] | 100 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 101 | | MD5 Digest[12-15] | 102 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 103 | */ 104 | 105 | 106 | struct tddp_hdr{ 107 | uint8_t version; 108 | uint8_t type; 109 | uint8_t code; 110 | uint8_t replyinfo; 111 | uint32_t pktlength; 112 | uint16_t pktid; 113 | uint8_t subtype; 114 | uint8_t res; 115 | uint8_t md5_digest[16]; 116 | } __attribute__ ((__packed__)); 117 | 118 | #define TDDP_RECEIVE_PORT 61000 119 | #define TDDP_SERVICE_PORT 1040 120 | 121 | char TP_LINK_IP_CAMERA_DISCOVER[]={0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x17, 0x00, \ 122 | 0x07, 0xd8, 0xa1, 0x4f, 0xc2, 0x90, 0x98, 0x93, 0xec, 0x5b, 0x80, 0x5e, \ 123 | 0xfa, 0xe2, 0x06, 0xd5, 0x63, 0x86, 0xb6, 0xdc, 0x3c, 0x8a, 0xff, 0x48, \ 124 | 0xce, 0x6c, 0xbd, 0x97, 0xb7, 0x1c, 0x21, 0xe9, 0xbd, 0x59, 0x30, 0xd7, \ 125 | 0x19, 0xd1, 0x22, 0x77, 0x6b, 0xd9, 0x43, 0x19, 0xd8, 0x87, 0x9f, 0xbb}; 126 | 127 | char *commands[]={"reboot", "reset", "set_relay_state", "set_led_off", "set_dev_alias", "set_mac_addr", "set_device_id", "set_hw_id",\ 128 | "set_dev_location", "test_check_uboot", "get_dev_icon", "set_dev_icon", "set_test_mode", "download_firmware", 129 | "get_download_state", "flash_firmware", "check_new_config", "get_info", "get_sys_info", "get_emeter_info", NULL}; 130 | 131 | char TP_LINK_SMART_DISCOVER[]="{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}"; 132 | char TP_LINK_SET_RELAY_ON[]= "{\"system\":{\"set_relay_state\":{\"state\":1}}}"; 133 | char TP_LINK_SET_RELAY_OFF[]="{\"system\":{\"set_relay_state\":{\"state\":0}}}"; 134 | char TP_LINK_PING_PONG[]="{\"DoSme\":{\"err_code\":-1,\"err_msg\":\"module not support\"}}"; 135 | 136 | unsigned int is_command_valid(char *); 137 | void print_tddp_packet(void *, unsigned int); 138 | 139 | -------------------------------------------------------------------------------- /tools/iot-tddp.h~: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the iot-scanner tool 3 | * 4 | */ 5 | 6 | #define BUFFER_SIZE 65556 7 | 8 | /* Constants used with the multi_scan_local() function */ 9 | #define PROBE_ICMP6_ECHO 1 10 | #define PROBE_UNREC_OPT 2 11 | #define PROBE_TCP 3 12 | #define LOCAL_SRC 1 13 | #define GLOBAL_SRC 2 14 | 15 | #define ICMPV6_ECHO_PAYLOAD_SIZE 56 16 | #define MAX_IPV6_ENTRIES 65000 17 | 18 | /* Constant for the host-scanning functions */ 19 | #define PRINT_ETHER_ADDR 1 20 | #define NOT_PRINT_ETHER_ADDR 0 21 | 22 | #define VALID_MAPPING 1 23 | #define INVALID_MAPPING 0 24 | 25 | 26 | /* Remote scans */ 27 | #define LOW_BYTE_1ST_WORD_UPPER 0x1500 28 | #define LOW_BYTE_2ND_WORD_UPPER 0x0100 29 | #define EMBEDDED_PORT_2ND_WORD 5 30 | #define MAX_IEEE_OUIS_LINE_SIZE 160 31 | #define OUI_HEX_STRING_SIZE 5 32 | #define MAX_IEEE_OUIS 1000 33 | #define MAX_SCAN_ENTRIES 65535 34 | #define MAX_PORT_ENTRIES 65536 35 | #define MAX_PREF_ENTRIES MAX_SCAN_ENTRIES 36 | #define SELECT_TIMEOUT 4 37 | #define PSCAN_TIMEOUT 1 38 | #define MAX_RANGE_STR_LEN 79 39 | #define MIN_INC_RANGE 1000 40 | /* #define MAX_DESTNATIONS 65535 */ 41 | #define MAX_IID_ENTRIES 65535 42 | 43 | #define ND_RETRIES 0 44 | 45 | /* Constants for config file processing */ 46 | #define MAX_LINE_SIZE 250 47 | #define MAX_VAR_NAME_LEN 100 48 | #define MAX_FILENAME_SIZE 250 49 | 50 | 51 | union my6_addr{ 52 | uint8_t s6addr[16]; 53 | uint16_t s6addr16[8]; 54 | uint32_t s6addr32[4]; 55 | struct in6_addr in6_addr; 56 | }; 57 | 58 | 59 | #define MAX_PORTS_LINE_SIZE 80 60 | 61 | 62 | 63 | /* Constants for port scan results */ 64 | 65 | #define PORT_FILTERED 1 66 | #define PORT_OPEN 2 67 | #define PORT_CLOSED 4 68 | #define PORT_ACT_FILT 8 69 | 70 | 71 | #define DEFAULT_MIN_PORT 0 72 | #define DEFAULT_MAX_PORT 65535 73 | #define MAX_PORT_RANGE 65536 74 | #define IPPROTO_ALL 0xf1 /* Fake number to indicate both TCP and UDP */ 75 | 76 | #define SET_RELAY_ON 1 77 | #define SET_RELAY_OFF 2 78 | 79 | /* Constants for printing the scanning results */ 80 | 81 | /* Steps into which results will be printed */ 82 | /*#define MAX_STEPS 20*/ 83 | #define MAX_COMMAND_LENGTH 500 84 | 85 | /* 86 | 0 1 2 3 87 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 88 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 89 | | Ver | Type | Code | ReplyInfo | 90 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 91 | | PktLength | 92 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 93 | | PktID | SubType | Reserve | 94 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 95 | | MD5 Digest[0-3] | 96 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 97 | | MD5 Digest[4-7] | 98 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 99 | | MD5 Digest[8-11] | 100 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 101 | | MD5 Digest[12-15] | 102 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 103 | */ 104 | 105 | 106 | struct tddp_hdr{ 107 | uint8_t version; 108 | uint8_t type; 109 | uint8_t code; 110 | uint8_t replyinfo; 111 | uint32_t pktlength; 112 | uint16_t pktid; 113 | uint8_t subtype; 114 | uint8_t res; 115 | uint8_t md5_digest[16]; 116 | } __attribute__ ((__packed__)); 117 | 118 | #define TDDP_RECEIVE_PORT 61000 119 | #define TDDP_SERVICE_PORT 1040 120 | 121 | char *commands[]={"reboot", "reset", "set_relay_state", "set_led_off", "set_dev_alias", "set_mac_addr", "set_device_id", "set_hw_id",\ 122 | "set_dev_location", "test_check_uboot", "get_dev_icon", "set_dev_icon", "set_test_mode", "download_firmware", 123 | "get_download_state", "flash_firmware", "check_new_config", "get_info", "get_sys_info", "get_emeter_info", NULL}; 124 | 125 | char TP_LINK_SMART_DISCOVER[]="{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}"; 126 | char TP_LINK_SET_RELAY_ON[]= "{\"system\":{\"set_relay_state\":{\"state\":1}}}"; 127 | char TP_LINK_SET_RELAY_OFF[]="{\"system\":{\"set_relay_state\":{\"state\":0}}}"; 128 | char TP_LINK_PING_PONG[]="{\"DoSme\":{\"err_code\":-1,\"err_msg\":\"module not support\"}}"; 129 | 130 | unsigned int is_command_valid(char *); 131 | void print_tddp_packet(void *, unsigned int); 132 | 133 | -------------------------------------------------------------------------------- /tools/iot-tl-plug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header file for the iot-scanner tool 3 | * 4 | */ 5 | 6 | #define BUFFER_SIZE 65556 7 | 8 | /* Constants used with the multi_scan_local() function */ 9 | #define PROBE_ICMP6_ECHO 1 10 | #define PROBE_UNREC_OPT 2 11 | #define PROBE_TCP 3 12 | #define LOCAL_SRC 1 13 | #define GLOBAL_SRC 2 14 | 15 | #define ICMPV6_ECHO_PAYLOAD_SIZE 56 16 | #define MAX_IPV6_ENTRIES 65000 17 | 18 | /* Constant for the host-scanning functions */ 19 | #define PRINT_ETHER_ADDR 1 20 | #define NOT_PRINT_ETHER_ADDR 0 21 | 22 | #define VALID_MAPPING 1 23 | #define INVALID_MAPPING 0 24 | 25 | 26 | /* Remote scans */ 27 | #define LOW_BYTE_1ST_WORD_UPPER 0x1500 28 | #define LOW_BYTE_2ND_WORD_UPPER 0x0100 29 | #define EMBEDDED_PORT_2ND_WORD 5 30 | #define MAX_IEEE_OUIS_LINE_SIZE 160 31 | #define OUI_HEX_STRING_SIZE 5 32 | #define MAX_IEEE_OUIS 1000 33 | #define MAX_SCAN_ENTRIES 65535 34 | #define MAX_PORT_ENTRIES 65536 35 | #define MAX_PREF_ENTRIES MAX_SCAN_ENTRIES 36 | #define SELECT_TIMEOUT 4 37 | #define PSCAN_TIMEOUT 1 38 | #define MAX_RANGE_STR_LEN 79 39 | #define MIN_INC_RANGE 1000 40 | /* #define MAX_DESTNATIONS 65535 */ 41 | #define MAX_IID_ENTRIES 65535 42 | 43 | #define ND_RETRIES 0 44 | 45 | /* Constants for config file processing */ 46 | #define MAX_LINE_SIZE 250 47 | #define MAX_VAR_NAME_LEN 100 48 | #define MAX_FILENAME_SIZE 250 49 | 50 | 51 | union my6_addr{ 52 | uint8_t s6addr[16]; 53 | uint16_t s6addr16[8]; 54 | uint32_t s6addr32[4]; 55 | struct in6_addr in6_addr; 56 | }; 57 | 58 | 59 | #define MAX_PORTS_LINE_SIZE 80 60 | 61 | 62 | 63 | /* Constants for port scan results */ 64 | 65 | #define PORT_FILTERED 1 66 | #define PORT_OPEN 2 67 | #define PORT_CLOSED 4 68 | #define PORT_ACT_FILT 8 69 | 70 | 71 | #define DEFAULT_MIN_PORT 0 72 | #define DEFAULT_MAX_PORT 65535 73 | #define MAX_PORT_RANGE 65536 74 | #define IPPROTO_ALL 0xf1 /* Fake number to indicate both TCP and UDP */ 75 | 76 | #define SET_RELAY_ON 1 77 | #define SET_RELAY_OFF 2 78 | 79 | /* Constants for printing the scanning results */ 80 | 81 | /* Steps into which results will be printed */ 82 | /*#define MAX_STEPS 20*/ 83 | #define MAX_COMMAND_LENGTH 500 84 | 85 | char *commands[]={"reboot", "reset", "set_relay_state", "set_led_off", "set_dev_alias", "set_mac_addr", "set_device_id", "set_hw_id",\ 86 | "set_dev_location", "test_check_uboot", "get_dev_icon", "set_dev_icon", "set_test_mode", "download_firmware", 87 | "get_download_state", "flash_firmware", "check_new_config", "get_info", "get_sys_info", "get_emeter_info", NULL}; 88 | 89 | char TP_LINK_SMART_DISCOVER[]="{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}"; 90 | char TP_LINK_SET_RELAY_ON[]= "{\"system\":{\"set_relay_state\":{\"state\":1}}}"; 91 | char TP_LINK_SET_RELAY_OFF[]="{\"system\":{\"set_relay_state\":{\"state\":0}}}"; 92 | char TP_LINK_PING_PONG[]="{\"DoSme\":{\"err_code\":-1,\"err_msg\":\"module not support\"}}"; 93 | 94 | unsigned int is_command_valid(char *); 95 | 96 | 97 | -------------------------------------------------------------------------------- /tools/iot-toolkit.h: -------------------------------------------------------------------------------- 1 | #define SI6_TOOLKIT "SI6 Networks' IoT Toolkit v0.1 (Troopers 10)" 2 | #define MAX_CMDLINE_OPT_LEN 40 3 | #define DATE_STR_LEN 40 4 | 5 | -------------------------------------------------------------------------------- /tools/libiot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libiot : An IoT Library 3 | * 4 | * Copyright (C) 2017 Fernando Gont 5 | * 6 | * Programmed by Fernando Gont for SI6 Networks 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * Build with: make libiot 22 | * 23 | * It requires that the libpcap library be installed on your system. 24 | * 25 | * Please send any bug reports to Fernando Gont 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #ifdef __linux__ 42 | #include 43 | #include 44 | #include 45 | #include /* For datalink structure */ 46 | #elif defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__sun) || defined(sun) 47 | #include 48 | #include 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | 64 | #include "libiot.h" 65 | #include "iot-toolkit.h" 66 | 67 | 68 | /* pcap variables */ 69 | char errbuf[PCAP_ERRBUF_SIZE]; 70 | struct bpf_program pcap_filter; 71 | 72 | #ifdef __linux__ 73 | /* Netlink requests */ 74 | struct nlrequest{ 75 | struct nlmsghdr nl; 76 | struct rtmsg rt; 77 | char buf[MAX_NLPAYLOAD]; 78 | }; 79 | #endif 80 | 81 | 82 | 83 | 84 | /* 85 | * Function: init_iface_data() 86 | * 87 | * Initializes the contents of "iface_data" structure 88 | */ 89 | 90 | int init_iface_data(struct iface_data *idata){ 91 | unsigned int i; 92 | 93 | memset(idata, 0, sizeof(struct iface_data)); 94 | 95 | idata->mtu= ETH_DATA_LEN; 96 | idata->local_retrans = 0; 97 | idata->local_timeout = 1; 98 | 99 | if( (idata->ip6_global.prefix= malloc(MAX_LOCAL_ADDRESSES * sizeof(struct prefix_entry *))) == NULL) 100 | return(FAILURE); 101 | 102 | idata->ip6_global.nprefix=0; 103 | idata->ip6_global.maxprefix= MAX_LOCAL_ADDRESSES; 104 | 105 | if( (idata->prefix_ol.prefix= malloc(MAX_PREFIXES_ONLINK * sizeof(struct prefix_entry *))) == NULL) 106 | return(FAILURE); 107 | 108 | idata->prefix_ol.nprefix= 0; 109 | idata->prefix_ol.maxprefix= MAX_PREFIXES_ONLINK; 110 | 111 | if( (idata->prefix_ac.prefix= malloc(MAX_PREFIXES_AUTO * sizeof(struct prefix_entry *))) == NULL) 112 | return(FAILURE); 113 | 114 | idata->prefix_ac.nprefix= 0; 115 | idata->prefix_ac.maxprefix= MAX_PREFIXES_AUTO; 116 | 117 | if( ((idata->iflist).ifaces= malloc(sizeof(struct iface_entry) * MAX_IFACES)) == NULL) 118 | return(FAILURE); 119 | 120 | memset((idata->iflist).ifaces, 0, sizeof(struct iface_entry) * MAX_IFACES); 121 | 122 | idata->iflist.nifaces=0; 123 | idata->iflist.maxifaces= MAX_IFACES; 124 | 125 | for(i=0; iiflist).ifaces[i].ip6_global.prefix= malloc( sizeof(struct prefix_entry *) * MAX_LOCAL_ADDRESSES)) == NULL){ 127 | return(FAILURE); 128 | } 129 | 130 | (idata->iflist).ifaces[i].ip6_global.maxprefix= MAX_LOCAL_ADDRESSES; 131 | 132 | if( ((idata->iflist).ifaces[i].ip6_local.prefix= malloc( sizeof(struct prefix_entry *) * MAX_LOCAL_ADDRESSES)) == NULL){ 133 | return(FAILURE); 134 | } 135 | 136 | (idata->iflist).ifaces[i].ip6_local.maxprefix= MAX_LOCAL_ADDRESSES; 137 | 138 | if( ((idata->iflist).ifaces[i].ip.prefix= malloc( sizeof(struct prefixv4_entry *) * MAX_LOCAL_ADDRESSES)) == NULL){ 139 | return(FAILURE); 140 | } 141 | 142 | (idata->iflist).ifaces[i].ip.maxprefix= MAX_LOCAL_ADDRESSES; 143 | } 144 | 145 | return SUCCESS; 146 | } 147 | 148 | 149 | 150 | 151 | /* 152 | * Function: get_local_addrs() 153 | * 154 | * Obtains all local addresses (Ethernet and IPv6 addresses for all interfaces) 155 | */ 156 | 157 | int get_local_addrs(struct iface_data *idata){ 158 | struct iface_entry *cif; 159 | struct ifaddrs *ifptr, *ptr; 160 | struct sockaddr_in6 *sockin6ptr; 161 | struct sockaddr_in *sockinptr; 162 | 163 | #ifdef __linux__ 164 | struct sockaddr_ll *sockpptr; 165 | #elif defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) 166 | struct sockaddr_dl *sockpptr; 167 | #endif 168 | 169 | if(getifaddrs(&ifptr) != 0){ 170 | if(idata->verbose_f > 1){ 171 | puts("Error in call to getifaddrs()"); 172 | } 173 | return(FAILURE); 174 | } 175 | 176 | for(ptr=ifptr; ptr != NULL; ptr= ptr->ifa_next){ 177 | if(ptr->ifa_addr == NULL){ 178 | continue; 179 | } 180 | 181 | if(ptr->ifa_name == NULL){ 182 | #ifdef DEBUG 183 | puts("DEBUG: ifa_name was null"); 184 | #endif 185 | continue; 186 | } 187 | 188 | if( (cif = find_iface_by_name( &(idata->iflist), ptr->ifa_name)) == NULL){ 189 | if(idata->iflist.nifaces >= MAX_IFACES) 190 | continue; 191 | else{ 192 | cif= &(idata->iflist.ifaces[idata->iflist.nifaces]); 193 | strncpy(cif->iface, ptr->ifa_name, IFACE_LENGTH-1); 194 | cif->iface[IFACE_LENGTH-1]=0; 195 | /* XXX: Cannot otherwise find the index for tun devices? */ 196 | cif->ifindex= if_nametoindex(cif->iface); 197 | idata->iflist.nifaces++; 198 | } 199 | } 200 | 201 | #ifdef __linux__ 202 | if((ptr->ifa_addr)->sa_family == AF_PACKET){ 203 | sockpptr = (struct sockaddr_ll *) (ptr->ifa_addr); 204 | 205 | if(sockpptr->sll_halen == ETHER_ADDR_LEN){ 206 | memcpy(&(cif->ether), sockpptr->sll_addr, ETHER_ADDR_LEN); 207 | cif->ether_f= TRUE; 208 | } 209 | 210 | cif->ifindex= sockpptr->sll_ifindex; 211 | } 212 | #elif defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) 213 | if((ptr->ifa_addr)->sa_family == AF_LINK){ 214 | sockpptr = (struct sockaddr_dl *) (ptr->ifa_addr); 215 | if(sockpptr->sdl_alen == ETHER_ADDR_LEN){ 216 | memcpy(&(cif->ether), (sockpptr->sdl_data + sockpptr->sdl_nlen), ETHER_ADDR_LEN); 217 | cif->ether_f= TRUE; 218 | } 219 | 220 | cif->ifindex= sockpptr->sdl_index; 221 | } 222 | #endif 223 | else if((ptr->ifa_addr)->sa_family == AF_INET){ 224 | sockinptr= (struct sockaddr_in *) (ptr->ifa_addr); 225 | 226 | if(is_ip_in_prefix_list( &(sockinptr->sin_addr), &(cif->ip))) 227 | continue; 228 | 229 | if(IN_IS_ADDR_LOOPBACK(&(sockinptr->sin_addr))) 230 | cif->flags= IFACE_LOOPBACK; 231 | 232 | if(cif->ip.nprefix >= cif->ip6_global.maxprefix) 233 | continue; 234 | 235 | if( (cif->ip.prefix[cif->ip.nprefix] = \ 236 | malloc(sizeof(struct prefixv4_entry))) == NULL){ 237 | if(idata->verbose_f > 1) 238 | puts("Error while storing Source Address"); 239 | 240 | freeifaddrs(ifptr); 241 | return(FAILURE); 242 | } 243 | 244 | (cif->ip.prefix[cif->ip.nprefix])->len = 32; 245 | (cif->ip.prefix[cif->ip.nprefix])->ip = sockinptr->sin_addr; 246 | cif->ip.nprefix++; 247 | } 248 | 249 | else if((ptr->ifa_addr)->sa_family == AF_INET6){ 250 | sockin6ptr= (struct sockaddr_in6 *) (ptr->ifa_addr); 251 | 252 | if(IN6_IS_ADDR_LINKLOCAL( &(sockin6ptr->sin6_addr))){ 253 | if(cif->ip6_local.nprefix >= cif->ip6_local.maxprefix) 254 | continue; 255 | 256 | if(is_ip6_in_prefix_list( &(sockin6ptr->sin6_addr), &(cif->ip6_local)) == TRUE) 257 | continue; 258 | 259 | if( (cif->ip6_local.prefix[cif->ip6_local.nprefix] = malloc(sizeof(struct prefix_entry))) == NULL){ 260 | if(idata->verbose_f > 1) 261 | puts("Error while storing Source Address"); 262 | 263 | freeifaddrs(ifptr); 264 | return(FAILURE); 265 | } 266 | 267 | (cif->ip6_local.prefix[cif->ip6_local.nprefix])->len = 128; 268 | (cif->ip6_local.prefix[cif->ip6_local.nprefix])->ip6 = sockin6ptr->sin6_addr; 269 | 270 | #if defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) 271 | /* BSDs store the interface index in s6_addr16[1], so we must clear it */ 272 | (cif->ip6_local.prefix[cif->ip6_local.nprefix])->ip6.s6_addr16[1] =0; 273 | (cif->ip6_local.prefix[cif->ip6_local.nprefix])->ip6.s6_addr16[2] =0; 274 | (cif->ip6_local.prefix[cif->ip6_local.nprefix])->ip6.s6_addr16[3] =0; 275 | #endif 276 | 277 | cif->ip6_local.nprefix++; 278 | } 279 | else{ 280 | if(is_ip6_in_prefix_list( &(sockin6ptr->sin6_addr), &(cif->ip6_global))) 281 | continue; 282 | 283 | if(IN6_IS_ADDR_LOOPBACK(&(sockin6ptr->sin6_addr))) 284 | cif->flags= IFACE_LOOPBACK; 285 | 286 | if(cif->ip6_global.nprefix >= cif->ip6_global.maxprefix) 287 | continue; 288 | 289 | if( (cif->ip6_global.prefix[cif->ip6_global.nprefix] = \ 290 | malloc(sizeof(struct prefix_entry))) == NULL){ 291 | if(idata->verbose_f > 1) 292 | puts("Error while storing Source Address"); 293 | 294 | freeifaddrs(ifptr); 295 | return(FAILURE); 296 | } 297 | 298 | (cif->ip6_global.prefix[cif->ip6_global.nprefix])->len = 128; 299 | (cif->ip6_global.prefix[cif->ip6_global.nprefix])->ip6 = sockin6ptr->sin6_addr; 300 | cif->ip6_global.nprefix++; 301 | } 302 | } 303 | } 304 | 305 | freeifaddrs(ifptr); 306 | 307 | #ifdef DEBUG 308 | debug_print_ifaces_data( &(idata->iflist)); 309 | #endif 310 | return(SUCCESS); 311 | } 312 | 313 | 314 | 315 | 316 | /* 317 | * Function: debug_print_ifaces_data() 318 | * 319 | * Prints the data correspoding to each interface 320 | */ 321 | 322 | void debug_print_iflist(struct iface_list *iflist){ 323 | unsigned int i, j; 324 | struct iface_entry *iface; 325 | char plinkaddr[ETHER_ADDR_PLEN]; 326 | char pv6addr[INET6_ADDRSTRLEN]; 327 | char pv4addr[16]; /* Space for xxx.xxx.xxx.xxx plus NULL */ 328 | 329 | for(i=0; i< iflist->nifaces; i++){ 330 | iface= iflist->ifaces +i; 331 | 332 | printf("DEBUG: Interface: %s (%d)\tFlags:%s%s\n", iface->iface, iface->ifindex, (iface->flags & IFACE_LOOPBACK)?" LOOPBACK":"",\ 333 | (iface->flags & IFACE_TUNNEL)?"TUNNEL":""); 334 | 335 | if(iface->ether_f){ 336 | if(ether_ntop(&(iface->ether), plinkaddr, sizeof(plinkaddr)) == 0){ 337 | puts("DEBUG: ether_ntop(): Error converting address"); 338 | exit(EXIT_FAILURE); 339 | } 340 | 341 | printf("DEBUG: Link address: %s\n", plinkaddr); 342 | } 343 | 344 | if( (iface->ip6_global).nprefix){ 345 | puts("DEBUG: Global addresses:"); 346 | 347 | for(j=0; j<(iface->ip6_global.nprefix); j++){ 348 | if(inet_ntop(AF_INET6, &((iface->ip6_global.prefix[j])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 349 | puts("DEBUG: inet_ntop(): Error converting IPv6 Address to presentation format"); 350 | exit(EXIT_FAILURE); 351 | } 352 | 353 | printf("DEBUG: %s\n", pv6addr); 354 | } 355 | } 356 | 357 | if( (iface->ip6_local).nprefix){ 358 | puts("DEBUG: Local addresses:"); 359 | 360 | for(j=0; j<(iface->ip6_local.nprefix); j++){ 361 | if(inet_ntop(AF_INET6, &((iface->ip6_local.prefix[j])->ip6), pv6addr, sizeof(pv6addr)) == NULL){ 362 | puts("DEBUG: inet_ntop(): Error converting IPv6 Address to presentation format"); 363 | exit(EXIT_FAILURE); 364 | } 365 | 366 | printf("DEBUG: %s\n", pv6addr); 367 | } 368 | } 369 | 370 | if( (iface->ip).nprefix){ 371 | puts("DEBUG: IPv4 addresses:"); 372 | 373 | for(j=0; j<(iface->ip.nprefix); j++){ 374 | if(inet_ntop(AF_INET, &((iface->ip.prefix[j])->ip), pv4addr, sizeof(pv4addr)) == NULL){ 375 | puts("DEBUG: inet_ntop(): Error converting IPv4 Address to presentation format"); 376 | exit(EXIT_FAILURE); 377 | } 378 | 379 | printf("DEBUG: %s\n", pv4addr); 380 | } 381 | } 382 | 383 | puts(""); 384 | } 385 | } 386 | 387 | 388 | 389 | /* 390 | * Function: find_iface_by_name() 391 | * 392 | * Finds an Interface (by name) in an Interface list 393 | */ 394 | 395 | void *find_iface_by_name(struct iface_list *iflist, char *iface){ 396 | unsigned int i; 397 | 398 | for(i=0; i < iflist->nifaces; i++){ 399 | if(strncmp((iflist->ifaces[i]).iface, iface, IFACE_LENGTH) == 0) 400 | return(&(iflist->ifaces[i])); 401 | } 402 | 403 | return(NULL); 404 | } 405 | 406 | 407 | /* 408 | * Function: find_iface_by_index() 409 | * 410 | * Finds an Interface (by index) in an Interface list 411 | */ 412 | 413 | void *find_iface_by_index(struct iface_list *iflist, int ifindex){ 414 | unsigned int i; 415 | 416 | for(i=0; i < iflist->nifaces; i++){ 417 | if((iflist->ifaces[i]).ifindex == ifindex) 418 | return(&(iflist->ifaces[i])); 419 | } 420 | 421 | return(NULL); 422 | } 423 | 424 | 425 | /* 426 | * Function: find_iface_by_addr() 427 | * 428 | * Finds an Interface (by IPv6 address) in an Interface list 429 | */ 430 | 431 | void *find_iface_by_addr(struct iface_list *iflist, void *addr, sa_family_t family){ 432 | unsigned int i; 433 | 434 | if(family == AF_INET6){ 435 | for(i=0; i < iflist->nifaces; i++){ 436 | if(is_ip6_in_prefix_list(addr, &((iflist->ifaces[i]).ip6_global)) || is_ip6_in_prefix_list(addr, &((iflist->ifaces[i]).ip6_local))) 437 | return(&(iflist->ifaces[i])); 438 | } 439 | 440 | return(NULL); 441 | } 442 | else if(family == AF_INET){ 443 | for(i=0; i < iflist->nifaces; i++){ 444 | if(is_ip_in_prefix_list(addr, &((iflist->ifaces[i]).ip))) 445 | return(&(iflist->ifaces[i])); 446 | } 447 | 448 | return(NULL); 449 | } 450 | else{ 451 | return(NULL); 452 | } 453 | } 454 | 455 | 456 | /* 457 | * Function: find_v4addr_for_iface() 458 | * 459 | * Finds an IPv4 address for an interface (by name) 460 | */ 461 | 462 | void *find_v4addr_for_iface(struct iface_list *iflist, char *iface){ 463 | unsigned int i; 464 | 465 | for(i=0; i < iflist->nifaces; i++){ 466 | if(strncmp((iflist->ifaces[i]).iface, iface, IFACE_LENGTH) == 0){ 467 | if( (iflist->ifaces[i]).ip.nprefix) 468 | return( &((iflist->ifaces[i]).ip.prefix[0])->ip); 469 | else 470 | return(NULL); 471 | } 472 | } 473 | 474 | return(NULL); 475 | } 476 | 477 | 478 | /* 479 | * Function: find_v4addr() 480 | * 481 | * Finds a non-loopback IPv4 address 482 | */ 483 | 484 | void *find_v4addr(struct iface_list *iflist){ 485 | unsigned int i, j; 486 | 487 | for(i=0; i < iflist->nifaces; i++){ 488 | for(j=0; j < iflist->ifaces[i].ip.nprefix; j++){ 489 | if(!IN_IS_ADDR_LOOPBACK(&(((iflist->ifaces[i]).ip.prefix[j])->ip))) 490 | return( &(((iflist->ifaces[i]).ip.prefix[j])->ip)); 491 | } 492 | } 493 | 494 | return(NULL); 495 | } 496 | 497 | 498 | 499 | /* 500 | * Function: Strnlen() 501 | * 502 | * Our own version of strnlen(), since some OSes do not support it. 503 | */ 504 | 505 | size_t Strnlen(const char *s, size_t maxlen){ 506 | size_t i=0; 507 | 508 | while(i < maxlen && s[i] != 0) 509 | i++; 510 | 511 | if(i < maxlen) 512 | return(i); 513 | else 514 | return(maxlen); 515 | } 516 | 517 | 518 | 519 | /* 520 | * Function: is_ip_in_prefix_list() 521 | * 522 | * Checks whether an IPv4 address is present in a prefix list. 523 | */ 524 | 525 | int is_ip_in_prefix_list(struct in_addr *target, struct prefixv4_list *plist){ 526 | unsigned int i; 527 | uint32_t mask32; 528 | 529 | for(i=0; i < plist->nprefix; i++){ 530 | mask32 = 0xffffffff << (32 - (plist->prefix[i])->len); 531 | 532 | if( (target->s_addr & htonl(mask32)) == ((plist->prefix[i])->ip.s_addr & htonl(mask32))) 533 | return TRUE; 534 | } 535 | 536 | return FALSE; 537 | } 538 | 539 | 540 | /* 541 | * Function: is_ip6_in_prefix_list() 542 | * 543 | * Checks whether an IPv6 address is present in an address list. 544 | */ 545 | 546 | int is_ip6_in_prefix_list(struct in6_addr *target, struct prefix_list *plist){ 547 | unsigned int i, j, full32, rest32; 548 | uint32_t mask32; 549 | 550 | for(i=0; i < plist->nprefix; i++){ 551 | full32=(plist->prefix[i])->len / 32; 552 | rest32=(plist->prefix[i])->len % 32; 553 | mask32 = 0xffffffff; 554 | 555 | for(j=0; j < full32; j++) 556 | if(target->s6_addr32[j] != (plist->prefix[i])->ip6.s6_addr32[j]) 557 | break; 558 | 559 | if(j == full32){ 560 | if(rest32 == 0) 561 | return TRUE; 562 | else{ 563 | mask32 = mask32 << (32 - rest32); 564 | 565 | if( (target->s6_addr32[full32] & htonl(mask32)) == ((plist->prefix[i])->ip6.s6_addr32[full32] & htonl(mask32))) 566 | return TRUE; 567 | } 568 | } 569 | } 570 | 571 | return FALSE; 572 | } 573 | 574 | 575 | 576 | /* 577 | * Function: ether_ntop() 578 | * 579 | * Convert binary Ethernet Address into printable foramt (an ASCII string) 580 | */ 581 | 582 | int ether_ntop(const struct ether_addr *ether, char *ascii, size_t s){ 583 | unsigned int r; 584 | 585 | if(s < ETHER_ADDR_PLEN) 586 | return 0; 587 | 588 | r=snprintf(ascii, s, "%02x:%02x:%02x:%02x:%02x:%02x", ether->a[0], ether->a[1], ether->a[2], ether->a[3], \ 589 | ether->a[4], ether->a[5]); 590 | 591 | if(r != 17) 592 | return 0; 593 | 594 | return 1; 595 | } 596 | 597 | 598 | /* 599 | * Function: ether_pton() 600 | * 601 | * Convert a string (printable Ethernet Address) into binary format 602 | */ 603 | 604 | int ether_pton(const char *ascii, struct ether_addr *etheraddr, unsigned int s){ 605 | unsigned int i, a[6]; 606 | 607 | if(s < ETHER_ADDR_LEN) 608 | return 0; 609 | 610 | if(ascii){ 611 | if( sscanf(ascii,"%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]) == 6){ 612 | for(i=0;i<6;i++) 613 | etheraddr->a[i]= a[i]; 614 | 615 | return 1; 616 | } 617 | } 618 | 619 | return 0; 620 | } 621 | 622 | 623 | 624 | 625 | /* 626 | * release_privileges() 627 | * 628 | * Releases superuser privileges by switching to the real uid and gid, or to nobody 629 | */ 630 | 631 | void release_privileges(void){ 632 | uid_t ruid; 633 | gid_t rgid; 634 | struct passwd *pwdptr; 635 | 636 | /* 637 | If the real UID is not root, we setuid() and setgid() to that user and group, releasing superuser 638 | privileges. Otherwise, if the real UID is 0, we try to setuid() to "nobody", releasing superuser 639 | privileges. 640 | */ 641 | if( (ruid=getuid()) && (rgid=getgid())){ 642 | if(setgid(rgid) == -1){ 643 | puts("Error while releasing superuser privileges (changing to real GID)"); 644 | exit(EXIT_FAILURE); 645 | } 646 | 647 | if(setuid(ruid) == -1){ 648 | puts("Error while releasing superuser privileges (changing to real UID)"); 649 | exit(EXIT_FAILURE); 650 | } 651 | } 652 | else{ 653 | if((pwdptr=getpwnam("nobody"))){ 654 | if(!pwdptr->pw_uid || !pwdptr->pw_gid){ 655 | puts("User 'nobody' has incorrect privileges"); 656 | exit(EXIT_FAILURE); 657 | } 658 | 659 | if(setgid(pwdptr->pw_gid) == -1){ 660 | puts("Error while releasing superuser privileges (changing to nobody's group)"); 661 | exit(EXIT_FAILURE); 662 | } 663 | 664 | if(setuid(pwdptr->pw_uid) == -1){ 665 | puts("Error while releasing superuser privileges (changing to 'nobody')"); 666 | exit(EXIT_FAILURE); 667 | } 668 | } 669 | } 670 | } 671 | 672 | 673 | 674 | /* 675 | * Function: tp_link_crypt() 676 | * 677 | * Releases memory allocated for holding IPv6 addresses and Ethernet addresses 678 | */ 679 | 680 | void tp_link_decrypt(unsigned char *p, size_t size){ 681 | unsigned char key= 171, c; 682 | unsigned int i; 683 | 684 | if(p != NULL && size > 0){ 685 | for(i=0; i 0){ 705 | for(i=0; i= lastprobe + delta 751 | */ 752 | 753 | int is_time_elapsed(struct timeval *curtime, struct timeval *lastprobe, unsigned long delta){ 754 | if( curtime->tv_sec > (lastprobe->tv_sec + delta / 1000000) ){ 755 | return(1); 756 | }else if( curtime->tv_sec == (lastprobe->tv_sec + delta / 1000000)){ 757 | if( curtime->tv_usec >= (lastprobe->tv_usec + delta % 1000000) ){ 758 | return(1); 759 | } 760 | } 761 | 762 | return(0); 763 | } 764 | 765 | 766 | 767 | 768 | /* 769 | * Function: is_valid_json_string() 770 | * 771 | * Performs some minimum sanity checks on JSON strings 772 | */ 773 | 774 | int is_valid_json_string(char *s, unsigned int len){ 775 | unsigned int i; 776 | int bracket_depth=0, curly_depth=0, quote_num=0, quoted_f=FALSE, openquote_f=FALSE; 777 | 778 | return(TRUE); 779 | 780 | if(s == NULL){ 781 | /*puts("string nulo");*/ 782 | return(FALSE); 783 | } 784 | 785 | for(i=0; i< len; i++){ 786 | if(s[i] == 0x00){ 787 | /*puts("Encontre 0x00");*/ 788 | return(FALSE); 789 | } 790 | 791 | if(openquote_f){ 792 | switch(s[i]){ 793 | case '\\': 794 | quoted_f= TRUE; 795 | break; 796 | 797 | case '"': 798 | if(quoted_f){ 799 | quoted_f= FALSE; 800 | } 801 | else{ 802 | openquote_f= FALSE; 803 | quote_num++; 804 | } 805 | 806 | break; 807 | 808 | default: 809 | quoted_f= FALSE; 810 | break; 811 | } 812 | } 813 | else{ 814 | switch(s[i]){ 815 | case '\\': 816 | quoted_f= TRUE; 817 | break; 818 | 819 | case '[': 820 | bracket_depth++; 821 | quoted_f= FALSE; 822 | break; 823 | 824 | case ']': 825 | bracket_depth--; 826 | quoted_f= FALSE; 827 | 828 | if(bracket_depth < 0){ 829 | /*puts("curly_depth < 0");*/ 830 | return(FALSE); 831 | } 832 | 833 | break; 834 | 835 | case '{': 836 | curly_depth++; 837 | quoted_f= FALSE; 838 | break; 839 | 840 | case '}': 841 | curly_depth--; 842 | quoted_f= FALSE; 843 | 844 | if(curly_depth < 0){ 845 | /*puts("curly_depth < 0"); */ 846 | return(FALSE); 847 | } 848 | 849 | break; 850 | 851 | case '"': 852 | if(quoted_f){ 853 | quoted_f= FALSE; 854 | } 855 | else{ 856 | openquote_f= TRUE; 857 | quote_num++; 858 | } 859 | 860 | break; 861 | 862 | default: 863 | quoted_f= FALSE; 864 | break; 865 | } 866 | } 867 | 868 | } 869 | 870 | /* 871 | if(quote_num % 2){ 872 | puts("quote num no es par"); 873 | } 874 | 875 | if(curly_depth != 0){ 876 | puts("curly_depth != 0"); 877 | } 878 | 879 | if(bracket_depth != 0){ 880 | puts("bracket_depth != 0"); 881 | } 882 | */ 883 | 884 | if(quote_num % 2 || curly_depth != 0 || bracket_depth != 0){ 885 | return(FALSE); 886 | } 887 | 888 | return(TRUE); 889 | } 890 | 891 | 892 | 893 | 894 | 895 | /* 896 | * Function: get_json_objects() 897 | * 898 | * Obtains the first-level JSON objects 899 | */ 900 | 901 | struct json * json_get_objects(char *s, unsigned int len){ 902 | struct json *json; 903 | unsigned int i; 904 | char *kstart=NULL, *kend=NULL, *vstart=NULL, *vend=NULL; 905 | char quoted_f=FALSE, open_quote_f=FALSE; 906 | int bracket_depth=0, curly_depth=0; 907 | 908 | /*puts("Voy a chequear string");*/ 909 | if(!is_valid_json_string(s, len)){ 910 | /*puts("String no valido");*/ 911 | return(NULL); 912 | } 913 | 914 | /*puts("String valido");*/ 915 | 916 | /*puts("Voy a hacer alloc");*/ 917 | if( (json=json_alloc_struct()) == NULL){ 918 | /*puts("No pude hacer alloc");*/ 919 | return(NULL); 920 | } 921 | 922 | /*puts("hice alloc"); */ 923 | 924 | for(i=0; i< len; i++){ 925 | if(open_quote_f){ 926 | switch(s[i]){ 927 | case '\\': 928 | quoted_f= TRUE; 929 | break; 930 | 931 | case '"': 932 | if(quoted_f){ 933 | quoted_f= FALSE; 934 | } 935 | else{ 936 | open_quote_f= FALSE; 937 | /* 938 | if(curly_depth == 1 && kstart != NULL && kend==NULL){ 939 | kend= s+i+1; 940 | vstart= s+i+1; 941 | } 942 | */ 943 | } 944 | 945 | break; 946 | 947 | default: 948 | quoted_f= FALSE; 949 | break; 950 | } 951 | } 952 | else{ 953 | switch(s[i]){ 954 | case '\\': 955 | quoted_f= TRUE; 956 | break; 957 | 958 | case '[': 959 | bracket_depth++; 960 | quoted_f= FALSE; 961 | break; 962 | 963 | case ']': 964 | bracket_depth--; 965 | quoted_f= FALSE; 966 | 967 | if(bracket_depth < 0) 968 | return(FALSE); 969 | 970 | break; 971 | 972 | case '{': 973 | curly_depth++; 974 | if(curly_depth == 1 && kstart==NULL) 975 | kstart= s+i+1; 976 | 977 | quoted_f= FALSE; 978 | break; 979 | 980 | case ':': 981 | if(curly_depth == 1 && kstart != NULL && kend==NULL){ 982 | kend= s+i; 983 | vstart= s+i+1; 984 | } 985 | 986 | quoted_f= FALSE; 987 | break; 988 | 989 | case ',': 990 | if(curly_depth == 1 && kstart != NULL && kend!=NULL && vstart!=NULL){ 991 | vend= s+i; 992 | 993 | if(!json_add_item(json, kstart, kend-kstart, vstart, vend-vstart)){ 994 | json_free_struct(json); 995 | return(FALSE); 996 | } 997 | 998 | kstart= s+i+1; 999 | kend= NULL; 1000 | vstart= NULL; 1001 | vend= NULL; 1002 | } 1003 | else if(curly_depth == 1 && kstart == NULL && kend==NULL && vstart==NULL && vend==NULL){ 1004 | kstart= s+i+1; 1005 | } 1006 | 1007 | quoted_f= FALSE; 1008 | break; 1009 | 1010 | case '}': 1011 | curly_depth--; 1012 | 1013 | if(curly_depth <= 1 && curly_depth >= 0 && kstart != NULL && kend!=NULL && vstart!=NULL){ 1014 | vend= s+i+curly_depth; 1015 | 1016 | if(!json_add_item(json, kstart, kend-kstart, vstart, vend-vstart)){ 1017 | json_free_struct(json); 1018 | return(FALSE); 1019 | } 1020 | 1021 | kstart= NULL; 1022 | kend= NULL; 1023 | vstart= NULL; 1024 | vend= NULL; 1025 | } 1026 | 1027 | quoted_f= FALSE; 1028 | 1029 | if(curly_depth < 0) 1030 | return(FALSE); 1031 | 1032 | break; 1033 | 1034 | case '"': 1035 | if(quoted_f){ 1036 | quoted_f= FALSE; 1037 | } 1038 | else{ 1039 | open_quote_f=TRUE; 1040 | } 1041 | 1042 | break; 1043 | 1044 | default: 1045 | quoted_f= FALSE; 1046 | break; 1047 | } 1048 | } 1049 | } 1050 | 1051 | return(json); 1052 | } 1053 | 1054 | 1055 | /* 1056 | * Function: json_alloc_struct() 1057 | * 1058 | * Obtains the first-level JSON objects 1059 | */ 1060 | 1061 | struct json * json_alloc_struct(void){ 1062 | struct json *json; 1063 | unsigned int i; 1064 | 1065 | /*puts("entre a alloc");*/ 1066 | /* XXX: Minimal check on the size of struct json 1067 | We have: 2 unsignet int, 2 arrays of MAX_ITEMS of unsigned in, 2 arrays of MAX_ITEMS of char * 1068 | */ 1069 | /*printf("tam mem: %li\n", sizeof(struct json));*/ 1070 | 1071 | if( (json= malloc(sizeof(struct json))) == NULL){ 1072 | return(NULL); 1073 | } 1074 | 1075 | /* 1076 | if( (json= malloc(sizeof(struct json))) == NULL){ 1077 | puts("no pude reservar memoria"); 1078 | return(NULL); 1079 | } 1080 | */ 1081 | 1082 | if(sizeof(struct json) < ( ( (2 + 2 * MAX_JSON_ITEMS) * sizeof(unsigned int)) + (2 * MAX_JSON_ITEMS * sizeof(char *)))){ 1083 | /*puts("Tamanio pequenio"); */ 1084 | free(json); 1085 | return(NULL); 1086 | } 1087 | 1088 | /*puts("Voy a inicializar"); */ 1089 | json->nitem=0; 1090 | json->maxitems= MAX_JSON_ITEMS; 1091 | 1092 | for(i=0; ikey[i]=NULL; 1094 | json->key_l[i]=0; 1095 | json->value[i]=NULL; 1096 | json->value_l[i]=0; 1097 | } 1098 | 1099 | /*puts("Ya vuelvo");*/ 1100 | return(json); 1101 | } 1102 | 1103 | 1104 | 1105 | /* 1106 | * Function: json_free_struct() 1107 | * 1108 | * Obtains the first-level JSON objects 1109 | */ 1110 | 1111 | int json_free_struct(struct json *json){ 1112 | unsigned int i; 1113 | 1114 | /* XXX: Minimal check on the size of struct json 1115 | We have: 2 unsignet int, 2 arrays of MAX_ITEMS of unsigned in, 2 arrays of MAX_ITEMS of char * 1116 | */ 1117 | 1118 | if(sizeof(struct json) < (((2+ 2 * MAX_JSON_ITEMS) * sizeof(unsigned int)) + (2* MAX_JSON_ITEMS * sizeof(char *)))) 1119 | return(FALSE); 1120 | 1121 | json->nitem=0; 1122 | json->maxitems= MAX_JSON_ITEMS; 1123 | 1124 | for(i=0; ikey[i]==NULL){ 1126 | free(json->key[i]); 1127 | } 1128 | if(json->value[i]==NULL){ 1129 | free(json->value[i]); 1130 | } 1131 | } 1132 | 1133 | free(json); 1134 | 1135 | return(TRUE); 1136 | } 1137 | 1138 | 1139 | 1140 | 1141 | /* 1142 | * Function: json_add_item() 1143 | * 1144 | * Add an item to a struct json 1145 | */ 1146 | 1147 | unsigned int json_add_item(struct json *json, char *kstart, unsigned int klen, char *vstart, unsigned int vlen){ 1148 | if(json->nitem >= json->maxitems) 1149 | return(FALSE); 1150 | 1151 | if( (json->key[json->nitem]= malloc(klen+1)) == NULL){ 1152 | return(FALSE); 1153 | } 1154 | 1155 | if( (json->value[json->nitem]= malloc(vlen+1)) == NULL){ 1156 | free(json->key[json->nitem]); 1157 | return(FALSE); 1158 | } 1159 | 1160 | memcpy(json->key[json->nitem], kstart, klen); 1161 | *(json->key[json->nitem]+klen)= 0x00; /* Null terminate the string if we mean to print it */ 1162 | json->key_l[json->nitem]= klen; 1163 | memcpy(json->value[json->nitem], vstart, vlen); 1164 | json->value_l[json->nitem]= vlen; 1165 | *(json->value[json->nitem]+vlen)= 0x00; /* Null terminate the string if we mean to print it */ 1166 | json->nitem++; 1167 | 1168 | return(TRUE); 1169 | } 1170 | 1171 | 1172 | 1173 | 1174 | /* 1175 | * Function: json_print_objects() 1176 | * 1177 | * Add an item to a struct json 1178 | */ 1179 | 1180 | void json_print_objects(struct json *json){ 1181 | unsigned int i; 1182 | 1183 | for(i=0; i < json->nitem; i++){ 1184 | printf("%s: %s\n", json->key[i], json->value[i]); 1185 | } 1186 | } 1187 | 1188 | 1189 | /* 1190 | * Function: json_get_value() 1191 | * 1192 | * Obtain the value for a given key 1193 | */ 1194 | 1195 | unsigned int json_get_value(struct json *json, struct json_value *json_value, char *key){ 1196 | unsigned int i, klen; 1197 | 1198 | klen= Strnlen(key, 50); /* 50 is an artificial length for the key */ 1199 | 1200 | for(i=0; i < json->nitem; i++){ 1201 | if(strncmp(json->key[i], key, klen) == 0){ 1202 | json_value->value= json->value[i]; 1203 | json_value->len= json->value_l[i]; 1204 | return(TRUE); 1205 | } 1206 | } 1207 | 1208 | return(FALSE); 1209 | } 1210 | 1211 | 1212 | /* 1213 | * Function: json_remove_quotes() 1214 | * 1215 | * Remove quotes in keys and values 1216 | */ 1217 | 1218 | unsigned int json_remove_quotes(struct json *json){ 1219 | char *buff; 1220 | unsigned int i; 1221 | 1222 | for(i=0; initem;i++){ 1223 | 1224 | /* We require opening and closing quotes in order to remove them */ 1225 | if(json->key_l[i] >= 2){ 1226 | if(*(json->key[i]) == '"' && *(json->key[i] + json->key_l[i] - 1) == '"'){ 1227 | /* In the speial case of an empty string, we do not really need to "copy" data */ 1228 | if(json->key_l[i] == 2){ 1229 | *(json->key[i])= 0x00; 1230 | json->key_l[i]=0; 1231 | } 1232 | else{ 1233 | /* We are going to remove two characters, but need space for the NULL byte */ 1234 | if( (buff=malloc(json->key_l[i] - 1)) == NULL){ 1235 | return(FALSE); 1236 | } 1237 | 1238 | /* Copy the string plus the NULL byte */ 1239 | memcpy(buff, (json->key[i]+1), json->key_l[i] - 2); /* memcpy(buff, (json->key[i]+1), json->key_l[i] - 1); */ 1240 | *(buff + json->key_l[i] - 2)= 0x00; 1241 | /* Herewe copy the text string, minus the two quote signs, plus the null byte */ 1242 | 1243 | memcpy(json->key[i], buff, json->key_l[i] - 1); 1244 | json->key_l[i]= json->key_l[i]-2; 1245 | free(buff); 1246 | } 1247 | } 1248 | } 1249 | 1250 | if(json->value_l[i] >= 2){ 1251 | if(*(json->value[i]) == '"' && *(json->value[i] + json->value_l[i] -1 ) == '"'){ 1252 | /* In the speial case of an empty string, we do not really need to "copy" data */ 1253 | if(json->value_l[i] == 2){ 1254 | *(json->value[i])= 0x00; 1255 | json->value_l[i]=0; 1256 | } 1257 | else{ 1258 | if( (buff=malloc(json->value_l[i] - 1)) == NULL){ 1259 | return(FALSE); 1260 | } 1261 | 1262 | memcpy(buff, (json->value[i]+1), json->value_l[i] - 2); 1263 | *(buff + json->value_l[i] - 2)= 0x00; 1264 | memcpy(json->value[i], buff, json->value_l[i] - 1); 1265 | json->value_l[i]= json->value_l[i]-2; 1266 | free(buff); 1267 | } 1268 | } 1269 | } 1270 | } 1271 | 1272 | return(TRUE); 1273 | } 1274 | 1275 | 1276 | 1277 | /* 1278 | * Function: in_chksum() 1279 | * 1280 | * Calculate the 16-bit Internet checksum 1281 | * The same algorithm is used for compute the UDP checksum and the 1282 | * IP checksum 1283 | */ 1284 | uint16_t in_chksum(uint16_t *addr, size_t len){ 1285 | size_t nleft; 1286 | unsigned int sum = 0; 1287 | uint16_t *w; 1288 | uint16_t answer = 0; 1289 | 1290 | nleft=len; 1291 | w=addr; 1292 | 1293 | while(nleft > 1) { 1294 | sum += *w++; 1295 | nleft -= 2; 1296 | } 1297 | 1298 | if(nleft == 1) { 1299 | *(unsigned char *) (&answer) = *(unsigned char *) w; 1300 | sum += answer; 1301 | } 1302 | 1303 | sum = (sum >> 16) + (sum & 0xffff); 1304 | sum += (sum >> 16); 1305 | answer = ~sum; 1306 | return(answer); 1307 | } 1308 | 1309 | -------------------------------------------------------------------------------- /tools/libiot.h: -------------------------------------------------------------------------------- 1 | #ifndef lib_pcap_pcap_h 2 | #include 3 | #endif 4 | 5 | #include 6 | #include /* For IFNAMSIZ */ 7 | 8 | /* General constants */ 9 | #define SUCCESS 1 10 | #define FAILURE 0 11 | #define TRUE 1 12 | #define FALSE 0 13 | 14 | #define ADDR_AUTO 2 15 | 16 | 17 | /* Constants used for Router Discovery */ 18 | #define MAX_PREFIXES_ONLINK 100 19 | #define MAX_PREFIXES_AUTO 100 20 | #define MAX_LOCAL_ADDRESSES 256 21 | 22 | 23 | #define LUI long unsigned int 24 | #define CHAR_CR 0x0d 25 | #define CHAR_LF 0x0a 26 | #define DATA_BUFFER_LEN 1000 27 | #define LINE_BUFFER_SIZE 80 28 | #define MAX_STRING_SIZE 10 /* For limiting strncmp */ 29 | #define MAX_RANGE_STR_LEN 79 /* For function that check for address ranges in string */ 30 | #define ETH_ALEN 6 /* Octets in one ethernet addr */ 31 | #define ETH_HLEN 14 /* Total octets in header. */ 32 | #define ETH_DATA_LEN 1500 /* Max. octets in payload */ 33 | #define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */ 34 | #define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ 35 | #define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ 36 | 37 | #define ETHER_ADDR_PLEN 18 /* Includes termination byte */ 38 | 39 | #define ETHER_ALLNODES_LINK_ADDR "33:33:00:00:00:01" 40 | #define ETHER_ALLROUTERS_LINK_ADDR "33:33:00:00:00:02" 41 | 42 | #define MIN_IPV6_HLEN 40 43 | #define MIN_IPV6_MTU 1280 44 | #define MIN_TCP_HLEN 20 45 | #define MIN_UDP_HLEN 8 46 | #define MIN_ICMP6_HLEN 8 47 | #define MIN_HBH_LEN 8 48 | #define MIN_EXT_HLEN 8 49 | #define IFACE_LENGTH IFNAMSIZ 50 | 51 | 52 | 53 | /* Constants used with the libcap functions */ 54 | #define PCAP_SNAP_LEN 65535 55 | #define PCAP_PROMISC 1 56 | #define PCAP_OPT 1 57 | #ifndef PCAP_NETMASK_UNKNOWN 58 | #define PCAP_NETMASK_UNKNOWN 0xffffffff 59 | #endif 60 | 61 | #if defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(sun) || defined(__sun) 62 | #define PCAP_TIMEOUT 1 63 | #else 64 | #define PCAP_TIMEOUT 0 65 | #endif 66 | 67 | 68 | struct ether_addr{ 69 | uint8_t a[ETHER_ADDR_LEN]; 70 | } __attribute__ ((__packed__)); 71 | 72 | /* For DLT_NULL encapsulation */ 73 | struct dlt_null 74 | { 75 | uint32_t family; /* Protocol Family */ 76 | } __attribute__ ((__packed__)); 77 | 78 | 79 | 80 | 81 | /* 82 | Different OSes employ different constants for specifying the byte order. 83 | We employ the native Linux one, and if not available, map the BSD, Mac 84 | OS, or Solaris into the Linux one. 85 | */ 86 | #ifndef __BYTE_ORDER 87 | #define __LITTLE_ENDIAN 1234 88 | #define __BIG_ENDIAN 4321 89 | 90 | /* Mac OS */ 91 | #if defined (__BYTE_ORDER__) 92 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 93 | #define __BYTE_ORDER __LITTLE_ENDIAN 94 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 95 | #define __BYTE_ORDER __BIG_ENDIAN 96 | #endif 97 | 98 | /* BSD */ 99 | #elif defined(_BYTE_ORDER) 100 | #if _BYTE_ORDER == _LITTLE_ENDIAN 101 | #define __BYTE_ORDER __LITTLE_ENDIAN 102 | #elif _BYTE_ORDER == _BIG_ENDIAN 103 | #define __BYTE_ORDER __BIG_ENDIAN 104 | #endif 105 | /* XXX: Solaris. There should be a better constant on which to check the byte order */ 106 | #elif defined(sun) || defined (__sun) 107 | #if defined(_BIT_FIELDS_LTOH) 108 | #define __BYTE_ORDER __LITTLE_ENDIAN 109 | #else 110 | #define __BYTE_ORDER __IG_ENDIAN 111 | #endif 112 | #endif 113 | #endif 114 | 115 | 116 | /* 10Mb/s ethernet header */ 117 | struct ether_header{ 118 | struct ether_addr dst; /* destination eth addr */ 119 | struct ether_addr src; /* source ether addr */ 120 | uint16_t ether_type; /* packet type ID field */ 121 | } __attribute__ ((__packed__)); 122 | 123 | 124 | /* BSD definition */ 125 | 126 | /* 127 | * Structure of an internet header, naked of options. 128 | */ 129 | struct ip_hdr 130 | { 131 | #if __BYTE_ORDER == __LITTLE_ENDIAN 132 | unsigned int ip_hl:4; /* header length */ 133 | unsigned int ip_v:4; /* version */ 134 | #endif 135 | #if __BYTE_ORDER == __BIG_ENDIAN 136 | unsigned int ip_v:4; /* version */ 137 | unsigned int ip_hl:4; /* header length */ 138 | #endif 139 | uint8_t ip_tos; /* type of service */ 140 | uint16_t ip_len; /* total length */ 141 | uint16_t ip_id; /* identification */ 142 | uint16_t ip_off; /* fragment offset field */ 143 | #define IP_RF 0x8000 /* reserved fragment flag */ 144 | #define IP_DF 0x4000 /* dont fragment flag */ 145 | #define IP_MF 0x2000 /* more fragments flag */ 146 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 147 | uint8_t ip_ttl; /* time to live */ 148 | uint8_t ip_p; /* protocol */ 149 | uint16_t ip_sum; /* checksum */ 150 | struct in_addr ip_src, ip_dst; /* source and dest address */ 151 | }; 152 | 153 | 154 | /* 155 | * TCP header. 156 | * Per RFC 793, September, 1981. 157 | */ 158 | struct tcp_hdr { 159 | uint16_t th_sport; /* source port */ 160 | uint16_t th_dport; /* destination port */ 161 | tcp_seq th_seq; /* sequence number */ 162 | tcp_seq th_ack; /* acknowledgement number */ 163 | #if __BYTE_ORDER == __LITTLE_ENDIAN 164 | uint32_t th_x2:4, /* (unused) */ 165 | th_off:4; /* data offset */ 166 | #endif 167 | # if __BYTE_ORDER == __BIG_ENDIAN 168 | uint32_t th_off:4, /* data offset */ 169 | th_x2:4; /* (unused) */ 170 | #endif 171 | uint8_t th_flags; 172 | #define TH_FIN 0x01 173 | #define TH_SYN 0x02 174 | #define TH_RST 0x04 175 | #define TH_PUSH 0x08 176 | #define TH_ACK 0x10 177 | #define TH_URG 0x20 178 | #define TH_ECE 0x40 179 | #define TH_CWR 0x80 180 | uint16_t th_win; /* window */ 181 | uint16_t th_sum; /* checksum */ 182 | uint16_t th_urp; /* urgent pointer */ 183 | }; 184 | 185 | /* 186 | 0 7 8 15 16 23 24 31 187 | +--------+--------+--------+--------+ 188 | | Source | Destination | 189 | | Port | Port | 190 | +--------+--------+--------+--------+ 191 | | | | 192 | | Length | Checksum | 193 | +--------+--------+--------+--------+ 194 | | 195 | | data octets ... 196 | +---------------- ... 197 | 198 | User Datagram Header Format 199 | */ 200 | 201 | struct udp_hdr{ 202 | uint16_t uh_sport; /* source port */ 203 | uint16_t uh_dport; /* destination port */ 204 | uint16_t uh_ulen; /* udp length */ 205 | uint16_t uh_sum; /* udp checksum */ 206 | } __attribute__ ((__packed__)); 207 | 208 | 209 | struct pseudohdr{ 210 | struct in_addr saddr; 211 | struct in_addr daddr; 212 | uint8_t mbz; 213 | uint8_t protocol; 214 | uint16_t length; 215 | } __attribute__ ((__packed__)); 216 | 217 | 218 | 219 | /* Definition of the Authentication Header 220 | 0 1 2 3 221 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 222 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 223 | | Next Header | Payload Len | RESERVED | 224 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 225 | | Security Parameters Index (SPI) | 226 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 227 | | Sequence Number Field | 228 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229 | | | 230 | + Integrity Check Value-ICV (variable) | 231 | | | 232 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 233 | */ 234 | struct ah_hdr{ 235 | uint8_t ah_nxt; /* Next Header */ 236 | uint8_t ah_len; /* Payload length */ 237 | uint16_t ah_rsvd; /* Reserved */ 238 | uint32_t ah_spi; /* Reserved */ 239 | uint32_t ah_seq; /* Reserved */ 240 | uint32_t ah_icv; /* Integrity Check Value - ICV */ 241 | } __attribute__ ((__packed__)); 242 | 243 | 244 | /* Definition of the Encapsulating Security Payload 245 | 246 | 0 1 2 3 247 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 248 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---- 249 | | Security Parameters Index (SPI) | ^Int. 250 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- 251 | | Sequence Number | |ered 252 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ---- 253 | | Payload Data* (variable) | | ^ 254 | ~ ~ | | 255 | | | |Conf. 256 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- 257 | | | Padding (0-255 bytes) | |ered* 258 | +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | 259 | | | Pad Length | Next Header | v v 260 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ------ 261 | | Integrity Check Value-ICV (variable) | 262 | ~ ~ 263 | | | 264 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 265 | */ 266 | struct esp_hdr{ 267 | uint32_t esp_spi; /* Reserved */ 268 | uint32_t esp_seq; /* Reserved */ 269 | uint32_t ah_payload; /* Integrity Check Value - ICV */ 270 | } __attribute__ ((__packed__)); 271 | 272 | 273 | 274 | #define ARP_REQUEST 1 275 | #define ARP_REPLY 2 276 | #define RARP_REQUEST 3 277 | #define RARP_REPLY 4 278 | 279 | struct arp_hdr{ 280 | struct ether_header ether; 281 | uint16_t hard_type; /* packet type ID field */ 282 | uint16_t prot_type; /* packet type ID field */ 283 | uint8_t hard_size; 284 | uint8_t prot_size; 285 | uint8_t op; 286 | struct ether_addr src_ether; 287 | struct in_addr src_ip; 288 | struct ether_addr tgt_ether; 289 | struct in_addr tgt_ip; 290 | } __attribute__ ((__packed__)); 291 | 292 | 293 | /* For obtaining an IPv6 target */ 294 | struct target_ipv6{ 295 | struct in6_addr ip6; /* IPv6 address */ 296 | char name [NI_MAXHOST]; /* Name */ 297 | char canonname [NI_MAXHOST]; /* Canonic name */ 298 | int res; /* Error code */ 299 | unsigned int flags; /* Value-result: Whether the canonic name is required/obtained */ 300 | }; 301 | 302 | struct prefix_entry{ 303 | struct in6_addr ip6; 304 | unsigned char len; 305 | }; 306 | 307 | struct prefix_list{ 308 | struct prefix_entry **prefix; 309 | unsigned int nprefix; 310 | unsigned int maxprefix; 311 | }; 312 | 313 | 314 | struct host_entry{ 315 | struct in6_addr ip6; 316 | struct ether_addr ether; 317 | unsigned char flag; 318 | struct host_entry *next; 319 | }; 320 | 321 | struct host_list{ 322 | struct host_entry **host; 323 | unsigned int nhosts; 324 | unsigned int maxhosts; 325 | }; 326 | 327 | struct hostv4_entry{ 328 | struct in_addr ip; 329 | struct ether_addr ether; 330 | unsigned char flag; 331 | }; 332 | 333 | struct hostv4_list{ 334 | struct host_entry *host; 335 | unsigned int nhosts; 336 | unsigned int maxhosts; 337 | }; 338 | 339 | 340 | struct address_list{ 341 | struct in6_addr *addr; 342 | unsigned int naddr; 343 | unsigned int maxaddr; 344 | }; 345 | 346 | struct prefixv4_entry{ 347 | struct in_addr ip; 348 | unsigned char len; 349 | }; 350 | 351 | struct prefixv4_list{ 352 | struct prefixv4_entry **prefix; 353 | unsigned int nprefix; 354 | unsigned int maxprefix; 355 | }; 356 | 357 | 358 | #define MAX_IFACES 25 359 | struct iface_entry{ 360 | int ifindex; 361 | char iface[IFACE_LENGTH]; 362 | struct ether_addr ether; 363 | unsigned char ether_f; 364 | struct prefix_list ip6_global; 365 | struct prefix_list ip6_local; 366 | struct prefixv4_list ip; 367 | int flags; 368 | }; 369 | 370 | struct iface_list{ 371 | struct iface_entry *ifaces; 372 | unsigned int nifaces; 373 | unsigned int maxifaces; 374 | }; 375 | 376 | 377 | /* Constants employed by decode_ipv6_address() */ 378 | 379 | #define IPV6_UNSPEC 1 380 | #define IPV6_MULTICAST 2 381 | #define IPV6_UNICAST 4 382 | 383 | #define UCAST_V4MAPPED 1 384 | #define UCAST_V4COMPAT 2 385 | #define UCAST_LINKLOCAL 4 386 | #define UCAST_SITELOCAL 8 387 | #define UCAST_UNIQUELOCAL 16 388 | #define UCAST_6TO4 32 389 | #define UCAST_TEREDO 64 390 | #define UCAST_GLOBAL 128 391 | #define UCAST_LOOPBACK 256 392 | 393 | #define MCAST_PERMANENT 512 394 | #define MCAST_NONPERMANENT 1024 395 | #define MCAST_INVALID 2048 396 | #define MCAST_UNICASTBASED 4096 397 | #define MCAST_EMBEDRP 8192 398 | #define MCAST_UNKNOWN 16384 399 | 400 | #define SCOPE_RESERVED 1 401 | #define SCOPE_INTERFACE 2 402 | #define SCOPE_LINK 4 403 | #define SCOPE_ADMIN 8 404 | #define SCOPE_SITE 16 405 | #define SCOPE_ORGANIZATION 32 406 | #define SCOPE_GLOBAL 64 407 | #define SCOPE_UNASSIGNED 128 408 | #define SCOPE_UNSPECIFIED 256 409 | 410 | #define IID_MACDERIVED 1 411 | #define IID_ISATAP 2 412 | #define IID_EMBEDDEDIPV4 4 413 | #define IID_EMBEDDEDIPV4_32 8192 414 | #define IID_EMBEDDEDIPV4_64 64 415 | #define IID_EMBEDDEDPORT 8 416 | #define IID_EMBEDDEDPORTREV 16 417 | #define IID_LOWBYTE 32 418 | #define IID_PATTERN_BYTES 128 419 | #define IID_RANDOM 256 420 | #define IID_TEREDO_RFC4380 512 421 | #define IID_TEREDO_RFC5991 1024 422 | #define IID_TEREDO_UNKNOWN 2048 423 | #define IID_UNSPECIFIED 4096 424 | 425 | 426 | 427 | /* This struture is employed by decode_ipv6_address */ 428 | struct decode6{ 429 | struct in6_addr ip6; 430 | unsigned int type; 431 | unsigned int subtype; 432 | unsigned int scope; 433 | unsigned int iidtype; 434 | unsigned int iidsubtype; 435 | }; 436 | 437 | 438 | /* Macros for IPv4 Addresses */ 439 | #ifndef IN_IS_ADDR_LOOPBACK 440 | #define IN_IS_ADDR_LOOPBACK(a) \ 441 | (( *((uint32_t *) (a)) & htonl (0xff000000)) \ 442 | == htonl (0x7f000000)) 443 | #endif 444 | 445 | 446 | /* Macros for IPv6 Addresses */ 447 | #ifndef IN6_IS_ADDR_UNIQUELOCAL 448 | #define IN6_IS_ADDR_UNIQUELOCAL(a) \ 449 | ((((uint32_t *) (a))[0] & htonl (0xfe000000)) \ 450 | == htonl (0xfc000000)) 451 | #endif 452 | 453 | #ifndef IN6_IS_ADDR_6TO4 454 | #define IN6_IS_ADDR_6TO4(a) \ 455 | ((((uint32_t *) (a))[0] & htonl (0xffff0000)) \ 456 | == htonl (0x20020000)) 457 | #endif 458 | 459 | #ifndef IN6_IS_ADDR_TEREDO 460 | #define IN6_IS_ADDR_TEREDO(a) \ 461 | (((uint32_t *) (a))[0] == htonl (0x20020000)) 462 | #endif 463 | 464 | #ifndef IN6_IS_ADDR_TEREDO_LEGACY 465 | #define IN6_IS_ADDR_TEREDO_LEGACY(a) \ 466 | (((uint32_t *) (a))[0] == htonl (0x3ffe831f)) 467 | #endif 468 | 469 | 470 | 471 | 472 | #if defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) 473 | #ifndef s6_addr16 474 | #define s6_addr16 __u6_addr.__u6_addr16 475 | #endif 476 | 477 | #ifndef s6_addr 478 | #define s6_addr __u6_addr.__u6_addr8 479 | #endif 480 | 481 | #ifndef s6_addr8 482 | #define s6_addr8 __u6_addr.__u6_addr8 483 | #endif 484 | 485 | #ifndef s6_addr32 486 | #define s6_addr32 __u6_addr.__u6_addr32 487 | #endif 488 | #elif defined __linux__ || ( !defined(__FreeBSD__) && defined(__FreeBSD_kernel__)) 489 | #ifndef s6_addr16 490 | #define s6_addr16 __in6_u.__u6_addr16 491 | #endif 492 | 493 | #ifndef s6_addr32 494 | #define s6_addr32 __in6_u.__u6_addr32 495 | #endif 496 | #elif defined(__sun) || defined(sun) 497 | #ifndef s6_addr8 498 | #define s6_addr8 _S6_un._S6_u8 499 | #endif 500 | 501 | #ifndef s6_addr32 502 | #define s6_addr32 _S6_un._S6_u32 503 | #endif 504 | #endif 505 | 506 | 507 | /* This causes Linux to use the BSD definition of the TCP and UDP header fields */ 508 | #ifndef __FAVOR_BSD 509 | #define __FAVOR_BSD 510 | #endif 511 | 512 | 513 | /* Names (DNS, NI) related constants and definitions */ 514 | #define MAX_DOMAIN_LEN 512 515 | #define MAX_DNS_LABELS 50 516 | #define MAX_DNS_CLABELS 5 517 | 518 | 519 | /* RFC 4191 Router Advertisement Preference */ 520 | #define RTR_PREF_HIGH 0x01 521 | #define RTR_PREF_LOW 0x03 522 | #define RTR_PREF_MED 0x00 523 | #define RTR_PREF_RSVD 0x02 524 | 525 | /* ICMPv6 Types/Codes not defined in some OSes */ 526 | #ifndef ICMP6_DST_UNREACH_FAILEDPOLICY 527 | #define ICMP6_DST_UNREACH_FAILEDPOLICY 5 528 | #endif 529 | 530 | #ifndef ICMP6_DST_UNREACH_REJECTROUTE 531 | #define ICMP6_DST_UNREACH_REJECTROUTE 6 532 | #endif 533 | 534 | 535 | #if !(defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)) 536 | /* Definitions for Linux */ 537 | 538 | #ifndef _NETINET_ICMP6_H 539 | #include 540 | #endif 541 | 542 | #define ICMP6_NI_QUERY 139 /* node information request */ 543 | #define ICMP6_NI_REPLY 140 /* node information reply */ 544 | /* 545 | * icmp6 namelookup 546 | */ 547 | 548 | struct icmp6_namelookup { 549 | struct icmp6_hdr icmp6_nl_hdr; 550 | uint8_t icmp6_nl_nonce[8]; 551 | int32_t icmp6_nl_ttl; 552 | #if 0 553 | uint8_t icmp6_nl_len; 554 | uint8_t icmp6_nl_name[3]; 555 | #endif 556 | /* could be followed by options */ 557 | } __attribute__ ((__packed__)); 558 | 559 | /* 560 | * icmp6 node information 561 | */ 562 | struct icmp6_nodeinfo { 563 | struct icmp6_hdr icmp6_ni_hdr; 564 | uint8_t icmp6_ni_nonce[8]; 565 | /* could be followed by reply data */ 566 | } __attribute__ ((__packed__)); 567 | 568 | #define ni_type icmp6_ni_hdr.icmp6_type 569 | #define ni_code icmp6_ni_hdr.icmp6_code 570 | #define ni_cksum icmp6_ni_hdr.icmp6_cksum 571 | #define ni_qtype icmp6_ni_hdr.icmp6_data16[0] 572 | #define ni_flags icmp6_ni_hdr.icmp6_data16[1] 573 | 574 | #define NI_QTYPE_NOOP 0 /* NOOP */ 575 | #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */ 576 | #define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ 577 | #define NI_QTYPE_DNSNAME 2 /* DNS Name */ 578 | #define NI_QTYPE_NODEADDR 3 /* Node Addresses */ 579 | #define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ 580 | 581 | #if __BYTE_ORDER == __BIG_ENDIAN 582 | #define NI_SUPTYPE_FLAG_COMPRESS 0x1 583 | #define NI_FQDN_FLAG_VALIDTTL 0x1 584 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 585 | #define NI_SUPTYPE_FLAG_COMPRESS 0x0100 586 | #define NI_FQDN_FLAG_VALIDTTL 0x0100 587 | #endif 588 | 589 | #if __BYTE_ORDER == __BIG_ENDIAN 590 | #define NI_NODEADDR_FLAG_TRUNCATE 0x1 591 | #define NI_NODEADDR_FLAG_ALL 0x2 592 | #define NI_NODEADDR_FLAG_COMPAT 0x4 593 | #define NI_NODEADDR_FLAG_LINKLOCAL 0x8 594 | #define NI_NODEADDR_FLAG_SITELOCAL 0x10 595 | #define NI_NODEADDR_FLAG_GLOBAL 0x20 596 | #define NI_NODEADDR_FLAG_ANYCAST 0x40 /* just experimental. not in spec */ 597 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 598 | #define NI_NODEADDR_FLAG_TRUNCATE 0x0100 599 | #define NI_NODEADDR_FLAG_ALL 0x0200 600 | #define NI_NODEADDR_FLAG_COMPAT 0x0400 601 | #define NI_NODEADDR_FLAG_LINKLOCAL 0x0800 602 | #define NI_NODEADDR_FLAG_SITELOCAL 0x1000 603 | #define NI_NODEADDR_FLAG_GLOBAL 0x2000 604 | #define NI_NODEADDR_FLAG_ANYCAST 0x4000 /* just experimental. not in spec */ 605 | #endif 606 | 607 | struct ni_reply_fqdn { 608 | uint32_t ni_fqdn_ttl; /* TTL */ 609 | uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */ 610 | uint8_t ni_fqdn_name[3]; /* XXX: alignment */ 611 | } __attribute__ ((__packed__)); 612 | 613 | #endif 614 | 615 | 616 | struct ni_reply_ip6 { 617 | uint32_t ni_ip6_ttl; /* TTL */ 618 | struct in6_addr ip6; /* IPv6 address */ 619 | } __attribute__ ((__packed__)); 620 | 621 | 622 | struct ni_reply_ip { 623 | uint32_t ni_ip_ttl; /* TTL */ 624 | struct in_addr ip; /* IPv6 address */ 625 | } __attribute__ ((__packed__)); 626 | 627 | struct ni_reply_name { 628 | uint32_t ni_name_ttl; /* TTL */ 629 | unsigned char ni_name_name; /* IPv6 address */ 630 | } __attribute__ ((__packed__)); 631 | 632 | 633 | /* ICMPv6 Types/Codes not defined in some OSes */ 634 | #ifndef ICMP6_DST_UNREACH_FAILEDPOLICY 635 | #define ICMP6_DST_UNREACH_FAILEDPOLICY 5 636 | #endif 637 | 638 | #ifndef ICMP6_DST_UNREACH_REJECTROUTE 639 | #define ICMP6_DST_UNREACH_REJECTROUTE 6 640 | #endif 641 | 642 | 643 | struct packet{ 644 | unsigned char *link; 645 | unsigned char *ipv6; 646 | unsigned char *upper; 647 | unsigned long maxsize; 648 | }; 649 | 650 | struct iface_data{ 651 | char iface[IFACE_LENGTH]; 652 | unsigned char iface_f; 653 | pcap_t *pfd; 654 | int ifindex; 655 | unsigned char ifindex_f; 656 | struct iface_list iflist; 657 | unsigned int type; 658 | unsigned int flags; 659 | int fd; 660 | int fd2; 661 | unsigned int pending_write_f; 662 | void *pending_write_data; 663 | unsigned int pending_write_size; 664 | fd_set *rset; 665 | fd_set *wset; 666 | fd_set *eset; 667 | unsigned int write_errors; 668 | struct ether_addr ether; 669 | unsigned int ether_flag; 670 | unsigned int linkhsize; 671 | unsigned int max_packet_size; 672 | struct in6_addr ip6_local; 673 | unsigned int ip6_local_flag; 674 | struct prefix_list ip6_global; 675 | unsigned int ip6_global_flag; 676 | struct in6_addr router_ip6; 677 | struct ether_addr router_ether; 678 | struct prefix_list prefix_ac; 679 | struct prefix_list prefix_ol; 680 | unsigned int local_retrans; 681 | unsigned int local_timeout; 682 | unsigned int mtu; 683 | struct ether_addr hsrcaddr; 684 | unsigned int hsrcaddr_f; 685 | struct ether_addr hdstaddr; 686 | unsigned int hdstaddr_f; 687 | struct in_addr srcaddr; 688 | unsigned int src_f; /* XXX Set when a source address has been selected (even if automatically) */ 689 | unsigned int srcaddr_f; 690 | unsigned char srcpreflen; 691 | unsigned char srcprefix_f; 692 | struct in_addr dstaddr; 693 | unsigned int dstaddr_f; 694 | unsigned int verbose_f; 695 | unsigned char listen_f; 696 | unsigned char fragh_f; 697 | 698 | /* XXX 699 | The next four variables are kind of a duplicate of router_ip6 and router_ether above. 700 | May remove them at some point 701 | */ 702 | 703 | struct in6_addr nhaddr; 704 | unsigned char nhaddr_f; 705 | struct ether_addr nhhaddr; 706 | unsigned char nhhaddr_f; 707 | int nhifindex; 708 | unsigned char nhifindex_f; 709 | char nhiface[IFACE_LENGTH]; 710 | unsigned char nh_f; 711 | uint16_t srcport; 712 | uint16_t dstport; 713 | char srcport_f; 714 | char dstport_f; 715 | }; 716 | 717 | 718 | #ifdef __linux__ 719 | /* Consulting the routing table */ 720 | #define MAX_NLPAYLOAD 1024 721 | #else 722 | #define MAX_RTPAYLOAD 1024 723 | #endif 724 | 725 | #if defined(__linux__) 726 | 727 | #define SLL_ADDRLEN 0 728 | 729 | struct sll_linux{ 730 | uint16_t sll_pkttype; /* packet type */ 731 | uint16_t sll_hatype; /* link-layer address type */ 732 | uint16_t sll_halen; /* link-layer address length */ 733 | uint8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ 734 | uint16_t sll_protocol; /* protocol */ 735 | } __attribute__ ((__packed__)); 736 | #endif 737 | 738 | 739 | struct next_hop{ 740 | struct in6_addr srcaddr; 741 | unsigned char srcaddr_f; 742 | struct in6_addr dstaddr; 743 | unsigned char dstaddr_f; 744 | struct in6_addr nhaddr; 745 | unsigned char nhaddr_f; 746 | struct ether_addr nhhaddr; 747 | unsigned char nhhaddr_f; 748 | int ifindex; 749 | unsigned char ifindex_f; 750 | }; 751 | 752 | 753 | /* Flags that specify what the load_dst_and_pcap() function should do */ 754 | #define LOAD_PCAP_ONLY 0x01 755 | #define LOAD_SRC_NXT_HOP 0x02 756 | 757 | /* Constants to signal special interface types */ 758 | #define IFACE_LOOPBACK 1 759 | #define IFACE_TUNNEL 2 760 | 761 | #ifndef SA_SIZE 762 | #if defined(__APPLE__) 763 | #define SA_SIZE(sa) \ 764 | ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ 765 | sizeof(long) : \ 766 | ((struct sockaddr *)(sa))->sa_len ) 767 | #elif defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) 768 | #define SA_SIZE(sa) \ 769 | ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ 770 | sizeof(long) : \ 771 | 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) 772 | #else 773 | #define SA_SIZE(sa) sizeof(struct sockaddr) 774 | #endif 775 | #endif 776 | 777 | 778 | #define MAX_JSON_ITEMS 150 779 | 780 | struct json{ 781 | unsigned int nitem; 782 | unsigned int maxitems; /* MAX_ITEMS */ 783 | char *key[MAX_JSON_ITEMS]; 784 | unsigned int key_l[MAX_JSON_ITEMS]; 785 | char *value[MAX_JSON_ITEMS]; 786 | unsigned int value_l[MAX_JSON_ITEMS]; 787 | }; 788 | 789 | 790 | struct json_value{ 791 | char *value; 792 | unsigned int len; 793 | }; 794 | 795 | 796 | #define IP_LIMITED_MULTICAST "255.255.255.255" 797 | #define NULL_STRING "" 798 | #define TP_LINK_SMART_PORT 9999 799 | /* XXX Should use different constant */ 800 | #define MAX_TP_COMMAND_LENGTH 10000 801 | #define TP_LINK_IP_CAMERA_TDDP_PORT 1068 802 | 803 | 804 | int init_iface_data(struct iface_data *); 805 | void debug_print_iflist(struct iface_list *); 806 | int ether_ntop(const struct ether_addr *, char *, size_t); 807 | int ether_pton(const char *, struct ether_addr *, unsigned int); 808 | void *find_iface_by_index(struct iface_list *, int); 809 | void *find_iface_by_name(struct iface_list *, char *); 810 | void *find_iface_by_addr(struct iface_list *, void *, sa_family_t); 811 | void *find_v4addr(struct iface_list *); 812 | void *find_v4addr_for_iface(struct iface_list *, char *); 813 | int get_local_addrs(struct iface_data *); 814 | int is_ip_in_prefix_list(struct in_addr *, struct prefixv4_list *); 815 | int is_ip6_in_prefix_list(struct in6_addr *, struct prefix_list *); 816 | int is_time_elapsed(struct timeval *, struct timeval *, unsigned long); 817 | void release_privileges(void); 818 | size_t Strnlen(const char *, size_t); 819 | struct timeval timeval_sub(struct timeval *, struct timeval *); 820 | float time_diff_ms(struct timeval *, struct timeval *); 821 | void tp_link_crypt(unsigned char *, size_t); 822 | void tp_link_decrypt(unsigned char *, size_t); 823 | void dump_hex(void *, size_t); 824 | void dump_text(void* ptr, size_t s); 825 | 826 | 827 | 828 | 829 | int json_free_struct(struct json *); 830 | void json_print_objects(struct json *); 831 | unsigned int json_get_value(struct json *, struct json_value *, char *); 832 | struct json * json_get_objects(char *, unsigned int); 833 | unsigned int json_add_item(struct json *, char *, unsigned int, char *, unsigned int); 834 | struct json * json_alloc_struct(void); 835 | int is_valid_json_string(char *, unsigned int); 836 | unsigned int json_remove_quotes(struct json *); 837 | uint16_t in_chksum(uint16_t *, size_t); 838 | 839 | 840 | -------------------------------------------------------------------------------- /tools/libiot.h~: -------------------------------------------------------------------------------- 1 | #ifndef lib_pcap_pcap_h 2 | #include 3 | #endif 4 | 5 | #include 6 | #include /* For IFNAMSIZ */ 7 | 8 | /* General constants */ 9 | #define SUCCESS 1 10 | #define FAILURE 0 11 | #define TRUE 1 12 | #define FALSE 0 13 | 14 | #define ADDR_AUTO 2 15 | 16 | 17 | /* Constants used for Router Discovery */ 18 | #define MAX_PREFIXES_ONLINK 100 19 | #define MAX_PREFIXES_AUTO 100 20 | #define MAX_LOCAL_ADDRESSES 256 21 | 22 | 23 | #define LUI long unsigned int 24 | #define CHAR_CR 0x0d 25 | #define CHAR_LF 0x0a 26 | #define DATA_BUFFER_LEN 1000 27 | #define LINE_BUFFER_SIZE 80 28 | #define MAX_STRING_SIZE 10 /* For limiting strncmp */ 29 | #define MAX_RANGE_STR_LEN 79 /* For function that check for address ranges in string */ 30 | #define ETH_ALEN 6 /* Octets in one ethernet addr */ 31 | #define ETH_HLEN 14 /* Total octets in header. */ 32 | #define ETH_DATA_LEN 1500 /* Max. octets in payload */ 33 | #define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */ 34 | #define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ 35 | #define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ 36 | 37 | #define ETHER_ADDR_PLEN 18 /* Includes termination byte */ 38 | 39 | #define ETHER_ALLNODES_LINK_ADDR "33:33:00:00:00:01" 40 | #define ETHER_ALLROUTERS_LINK_ADDR "33:33:00:00:00:02" 41 | 42 | #define MIN_IPV6_HLEN 40 43 | #define MIN_IPV6_MTU 1280 44 | #define MIN_TCP_HLEN 20 45 | #define MIN_UDP_HLEN 8 46 | #define MIN_ICMP6_HLEN 8 47 | #define MIN_HBH_LEN 8 48 | #define MIN_EXT_HLEN 8 49 | #define IFACE_LENGTH IFNAMSIZ 50 | 51 | 52 | 53 | /* Constants used with the libcap functions */ 54 | #define PCAP_SNAP_LEN 65535 55 | #define PCAP_PROMISC 1 56 | #define PCAP_OPT 1 57 | #ifndef PCAP_NETMASK_UNKNOWN 58 | #define PCAP_NETMASK_UNKNOWN 0xffffffff 59 | #endif 60 | 61 | #if defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(sun) || defined(__sun) 62 | #define PCAP_TIMEOUT 1 63 | #else 64 | #define PCAP_TIMEOUT 0 65 | #endif 66 | 67 | 68 | struct ether_addr{ 69 | uint8_t a[ETHER_ADDR_LEN]; 70 | } __attribute__ ((__packed__)); 71 | 72 | /* For DLT_NULL encapsulation */ 73 | struct dlt_null 74 | { 75 | uint32_t family; /* Protocol Family */ 76 | } __attribute__ ((__packed__)); 77 | 78 | 79 | 80 | 81 | /* 82 | Different OSes employ different constants for specifying the byte order. 83 | We employ the native Linux one, and if not available, map the BSD, Mac 84 | OS, or Solaris into the Linux one. 85 | */ 86 | #ifndef __BYTE_ORDER 87 | #define __LITTLE_ENDIAN 1234 88 | #define __BIG_ENDIAN 4321 89 | 90 | /* Mac OS */ 91 | #if defined (__BYTE_ORDER__) 92 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 93 | #define __BYTE_ORDER __LITTLE_ENDIAN 94 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 95 | #define __BYTE_ORDER __BIG_ENDIAN 96 | #endif 97 | 98 | /* BSD */ 99 | #elif defined(_BYTE_ORDER) 100 | #if _BYTE_ORDER == _LITTLE_ENDIAN 101 | #define __BYTE_ORDER __LITTLE_ENDIAN 102 | #elif _BYTE_ORDER == _BIG_ENDIAN 103 | #define __BYTE_ORDER __BIG_ENDIAN 104 | #endif 105 | /* XXX: Solaris. There should be a better constant on which to check the byte order */ 106 | #elif defined(sun) || defined (__sun) 107 | #if defined(_BIT_FIELDS_LTOH) 108 | #define __BYTE_ORDER __LITTLE_ENDIAN 109 | #else 110 | #define __BYTE_ORDER __IG_ENDIAN 111 | #endif 112 | #endif 113 | #endif 114 | 115 | 116 | /* 10Mb/s ethernet header */ 117 | struct ether_header{ 118 | struct ether_addr dst; /* destination eth addr */ 119 | struct ether_addr src; /* source ether addr */ 120 | uint16_t ether_type; /* packet type ID field */ 121 | } __attribute__ ((__packed__)); 122 | 123 | 124 | /* BSD definition */ 125 | 126 | /* 127 | * Structure of an internet header, naked of options. 128 | */ 129 | struct ip_hdr 130 | { 131 | #if __BYTE_ORDER == __LITTLE_ENDIAN 132 | unsigned int ip_hl:4; /* header length */ 133 | unsigned int ip_v:4; /* version */ 134 | #endif 135 | #if __BYTE_ORDER == __BIG_ENDIAN 136 | unsigned int ip_v:4; /* version */ 137 | unsigned int ip_hl:4; /* header length */ 138 | #endif 139 | uint8_t ip_tos; /* type of service */ 140 | uint16_t ip_len; /* total length */ 141 | uint16_t ip_id; /* identification */ 142 | uint16_t ip_off; /* fragment offset field */ 143 | #define IP_RF 0x8000 /* reserved fragment flag */ 144 | #define IP_DF 0x4000 /* dont fragment flag */ 145 | #define IP_MF 0x2000 /* more fragments flag */ 146 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 147 | uint8_t ip_ttl; /* time to live */ 148 | uint8_t ip_p; /* protocol */ 149 | uint16_t ip_sum; /* checksum */ 150 | struct in_addr ip_src, ip_dst; /* source and dest address */ 151 | }; 152 | 153 | 154 | /* 155 | * TCP header. 156 | * Per RFC 793, September, 1981. 157 | */ 158 | struct tcp_hdr { 159 | uint16_t th_sport; /* source port */ 160 | uint16_t th_dport; /* destination port */ 161 | tcp_seq th_seq; /* sequence number */ 162 | tcp_seq th_ack; /* acknowledgement number */ 163 | #if __BYTE_ORDER == __LITTLE_ENDIAN 164 | uint32_t th_x2:4, /* (unused) */ 165 | th_off:4; /* data offset */ 166 | #endif 167 | # if __BYTE_ORDER == __BIG_ENDIAN 168 | uint32_t th_off:4, /* data offset */ 169 | th_x2:4; /* (unused) */ 170 | #endif 171 | uint8_t th_flags; 172 | #define TH_FIN 0x01 173 | #define TH_SYN 0x02 174 | #define TH_RST 0x04 175 | #define TH_PUSH 0x08 176 | #define TH_ACK 0x10 177 | #define TH_URG 0x20 178 | #define TH_ECE 0x40 179 | #define TH_CWR 0x80 180 | uint16_t th_win; /* window */ 181 | uint16_t th_sum; /* checksum */ 182 | uint16_t th_urp; /* urgent pointer */ 183 | }; 184 | 185 | /* 186 | 0 7 8 15 16 23 24 31 187 | +--------+--------+--------+--------+ 188 | | Source | Destination | 189 | | Port | Port | 190 | +--------+--------+--------+--------+ 191 | | | | 192 | | Length | Checksum | 193 | +--------+--------+--------+--------+ 194 | | 195 | | data octets ... 196 | +---------------- ... 197 | 198 | User Datagram Header Format 199 | */ 200 | 201 | struct udp_hdr{ 202 | uint16_t uh_sport; /* source port */ 203 | uint16_t uh_dport; /* destination port */ 204 | uint16_t uh_ulen; /* udp length */ 205 | uint16_t uh_sum; /* udp checksum */ 206 | } __attribute__ ((__packed__)); 207 | 208 | 209 | struct pseudohdr{ 210 | struct in_addr saddr; 211 | struct in_addr daddr; 212 | uint8_t mbz; 213 | uint8_t protocol; 214 | uint16_t length; 215 | } __attribute__ ((__packed__)); 216 | 217 | 218 | 219 | /* Definition of the Authentication Header 220 | 0 1 2 3 221 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 222 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 223 | | Next Header | Payload Len | RESERVED | 224 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 225 | | Security Parameters Index (SPI) | 226 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 227 | | Sequence Number Field | 228 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229 | | | 230 | + Integrity Check Value-ICV (variable) | 231 | | | 232 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 233 | */ 234 | struct ah_hdr{ 235 | uint8_t ah_nxt; /* Next Header */ 236 | uint8_t ah_len; /* Payload length */ 237 | uint16_t ah_rsvd; /* Reserved */ 238 | uint32_t ah_spi; /* Reserved */ 239 | uint32_t ah_seq; /* Reserved */ 240 | uint32_t ah_icv; /* Integrity Check Value - ICV */ 241 | } __attribute__ ((__packed__)); 242 | 243 | 244 | /* Definition of the Encapsulating Security Payload 245 | 246 | 0 1 2 3 247 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 248 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---- 249 | | Security Parameters Index (SPI) | ^Int. 250 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- 251 | | Sequence Number | |ered 252 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ---- 253 | | Payload Data* (variable) | | ^ 254 | ~ ~ | | 255 | | | |Conf. 256 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- 257 | | | Padding (0-255 bytes) | |ered* 258 | +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | 259 | | | Pad Length | Next Header | v v 260 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ------ 261 | | Integrity Check Value-ICV (variable) | 262 | ~ ~ 263 | | | 264 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 265 | */ 266 | struct esp_hdr{ 267 | uint32_t esp_spi; /* Reserved */ 268 | uint32_t esp_seq; /* Reserved */ 269 | uint32_t ah_payload; /* Integrity Check Value - ICV */ 270 | } __attribute__ ((__packed__)); 271 | 272 | 273 | 274 | #define ARP_REQUEST 1 275 | #define ARP_REPLY 2 276 | #define RARP_REQUEST 3 277 | #define RARP_REPLY 4 278 | 279 | struct arp_hdr{ 280 | struct ether_header ether; 281 | uint16_t hard_type; /* packet type ID field */ 282 | uint16_t prot_type; /* packet type ID field */ 283 | uint8_t hard_size; 284 | uint8_t prot_size; 285 | uint8_t op; 286 | struct ether_addr src_ether; 287 | struct in_addr src_ip; 288 | struct ether_addr tgt_ether; 289 | struct in_addr tgt_ip; 290 | } __attribute__ ((__packed__)); 291 | 292 | 293 | /* For obtaining an IPv6 target */ 294 | struct target_ipv6{ 295 | struct in6_addr ip6; /* IPv6 address */ 296 | char name [NI_MAXHOST]; /* Name */ 297 | char canonname [NI_MAXHOST]; /* Canonic name */ 298 | int res; /* Error code */ 299 | unsigned int flags; /* Value-result: Whether the canonic name is required/obtained */ 300 | }; 301 | 302 | struct prefix_entry{ 303 | struct in6_addr ip6; 304 | unsigned char len; 305 | }; 306 | 307 | struct prefix_list{ 308 | struct prefix_entry **prefix; 309 | unsigned int nprefix; 310 | unsigned int maxprefix; 311 | }; 312 | 313 | 314 | struct host_entry{ 315 | struct in6_addr ip6; 316 | struct ether_addr ether; 317 | unsigned char flag; 318 | struct host_entry *next; 319 | }; 320 | 321 | struct host_list{ 322 | struct host_entry **host; 323 | unsigned int nhosts; 324 | unsigned int maxhosts; 325 | }; 326 | 327 | struct hostv4_entry{ 328 | struct in_addr ip; 329 | struct ether_addr ether; 330 | unsigned char flag; 331 | }; 332 | 333 | struct hostv4_list{ 334 | struct host_entry *host; 335 | unsigned int nhosts; 336 | unsigned int maxhosts; 337 | }; 338 | 339 | 340 | struct address_list{ 341 | struct in6_addr *addr; 342 | unsigned int naddr; 343 | unsigned int maxaddr; 344 | }; 345 | 346 | struct prefixv4_entry{ 347 | struct in_addr ip; 348 | unsigned char len; 349 | }; 350 | 351 | struct prefixv4_list{ 352 | struct prefixv4_entry **prefix; 353 | unsigned int nprefix; 354 | unsigned int maxprefix; 355 | }; 356 | 357 | 358 | #define MAX_IFACES 25 359 | struct iface_entry{ 360 | int ifindex; 361 | char iface[IFACE_LENGTH]; 362 | struct ether_addr ether; 363 | unsigned char ether_f; 364 | struct prefix_list ip6_global; 365 | struct prefix_list ip6_local; 366 | struct prefixv4_list ip; 367 | int flags; 368 | }; 369 | 370 | struct iface_list{ 371 | struct iface_entry *ifaces; 372 | unsigned int nifaces; 373 | unsigned int maxifaces; 374 | }; 375 | 376 | 377 | /* Constants employed by decode_ipv6_address() */ 378 | 379 | #define IPV6_UNSPEC 1 380 | #define IPV6_MULTICAST 2 381 | #define IPV6_UNICAST 4 382 | 383 | #define UCAST_V4MAPPED 1 384 | #define UCAST_V4COMPAT 2 385 | #define UCAST_LINKLOCAL 4 386 | #define UCAST_SITELOCAL 8 387 | #define UCAST_UNIQUELOCAL 16 388 | #define UCAST_6TO4 32 389 | #define UCAST_TEREDO 64 390 | #define UCAST_GLOBAL 128 391 | #define UCAST_LOOPBACK 256 392 | 393 | #define MCAST_PERMANENT 512 394 | #define MCAST_NONPERMANENT 1024 395 | #define MCAST_INVALID 2048 396 | #define MCAST_UNICASTBASED 4096 397 | #define MCAST_EMBEDRP 8192 398 | #define MCAST_UNKNOWN 16384 399 | 400 | #define SCOPE_RESERVED 1 401 | #define SCOPE_INTERFACE 2 402 | #define SCOPE_LINK 4 403 | #define SCOPE_ADMIN 8 404 | #define SCOPE_SITE 16 405 | #define SCOPE_ORGANIZATION 32 406 | #define SCOPE_GLOBAL 64 407 | #define SCOPE_UNASSIGNED 128 408 | #define SCOPE_UNSPECIFIED 256 409 | 410 | #define IID_MACDERIVED 1 411 | #define IID_ISATAP 2 412 | #define IID_EMBEDDEDIPV4 4 413 | #define IID_EMBEDDEDIPV4_32 8192 414 | #define IID_EMBEDDEDIPV4_64 64 415 | #define IID_EMBEDDEDPORT 8 416 | #define IID_EMBEDDEDPORTREV 16 417 | #define IID_LOWBYTE 32 418 | #define IID_PATTERN_BYTES 128 419 | #define IID_RANDOM 256 420 | #define IID_TEREDO_RFC4380 512 421 | #define IID_TEREDO_RFC5991 1024 422 | #define IID_TEREDO_UNKNOWN 2048 423 | #define IID_UNSPECIFIED 4096 424 | 425 | 426 | 427 | /* This struture is employed by decode_ipv6_address */ 428 | struct decode6{ 429 | struct in6_addr ip6; 430 | unsigned int type; 431 | unsigned int subtype; 432 | unsigned int scope; 433 | unsigned int iidtype; 434 | unsigned int iidsubtype; 435 | }; 436 | 437 | 438 | /* Macros for IPv4 Addresses */ 439 | #ifndef IN_IS_ADDR_LOOPBACK 440 | #define IN_IS_ADDR_LOOPBACK(a) \ 441 | (( *((uint32_t *) (a)) & htonl (0xff000000)) \ 442 | == htonl (0x7f000000)) 443 | #endif 444 | 445 | 446 | /* Macros for IPv6 Addresses */ 447 | #ifndef IN6_IS_ADDR_UNIQUELOCAL 448 | #define IN6_IS_ADDR_UNIQUELOCAL(a) \ 449 | ((((uint32_t *) (a))[0] & htonl (0xfe000000)) \ 450 | == htonl (0xfc000000)) 451 | #endif 452 | 453 | #ifndef IN6_IS_ADDR_6TO4 454 | #define IN6_IS_ADDR_6TO4(a) \ 455 | ((((uint32_t *) (a))[0] & htonl (0xffff0000)) \ 456 | == htonl (0x20020000)) 457 | #endif 458 | 459 | #ifndef IN6_IS_ADDR_TEREDO 460 | #define IN6_IS_ADDR_TEREDO(a) \ 461 | (((uint32_t *) (a))[0] == htonl (0x20020000)) 462 | #endif 463 | 464 | #ifndef IN6_IS_ADDR_TEREDO_LEGACY 465 | #define IN6_IS_ADDR_TEREDO_LEGACY(a) \ 466 | (((uint32_t *) (a))[0] == htonl (0x3ffe831f)) 467 | #endif 468 | 469 | 470 | 471 | 472 | #if defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__) 473 | #ifndef s6_addr16 474 | #define s6_addr16 __u6_addr.__u6_addr16 475 | #endif 476 | 477 | #ifndef s6_addr 478 | #define s6_addr __u6_addr.__u6_addr8 479 | #endif 480 | 481 | #ifndef s6_addr8 482 | #define s6_addr8 __u6_addr.__u6_addr8 483 | #endif 484 | 485 | #ifndef s6_addr32 486 | #define s6_addr32 __u6_addr.__u6_addr32 487 | #endif 488 | #elif defined __linux__ || ( !defined(__FreeBSD__) && defined(__FreeBSD_kernel__)) 489 | #ifndef s6_addr16 490 | #define s6_addr16 __in6_u.__u6_addr16 491 | #endif 492 | 493 | #ifndef s6_addr32 494 | #define s6_addr32 __in6_u.__u6_addr32 495 | #endif 496 | #elif defined(__sun) || defined(sun) 497 | #ifndef s6_addr8 498 | #define s6_addr8 _S6_un._S6_u8 499 | #endif 500 | 501 | #ifndef s6_addr32 502 | #define s6_addr32 _S6_un._S6_u32 503 | #endif 504 | #endif 505 | 506 | 507 | /* This causes Linux to use the BSD definition of the TCP and UDP header fields */ 508 | #ifndef __FAVOR_BSD 509 | #define __FAVOR_BSD 510 | #endif 511 | 512 | 513 | /* Names (DNS, NI) related constants and definitions */ 514 | #define MAX_DOMAIN_LEN 512 515 | #define MAX_DNS_LABELS 50 516 | #define MAX_DNS_CLABELS 5 517 | 518 | 519 | /* RFC 4191 Router Advertisement Preference */ 520 | #define RTR_PREF_HIGH 0x01 521 | #define RTR_PREF_LOW 0x03 522 | #define RTR_PREF_MED 0x00 523 | #define RTR_PREF_RSVD 0x02 524 | 525 | /* ICMPv6 Types/Codes not defined in some OSes */ 526 | #ifndef ICMP6_DST_UNREACH_FAILEDPOLICY 527 | #define ICMP6_DST_UNREACH_FAILEDPOLICY 5 528 | #endif 529 | 530 | #ifndef ICMP6_DST_UNREACH_REJECTROUTE 531 | #define ICMP6_DST_UNREACH_REJECTROUTE 6 532 | #endif 533 | 534 | 535 | #if !(defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined(__APPLE__)) 536 | /* Definitions for Linux */ 537 | 538 | #ifndef _NETINET_ICMP6_H 539 | #include 540 | #endif 541 | 542 | #define ICMP6_NI_QUERY 139 /* node information request */ 543 | #define ICMP6_NI_REPLY 140 /* node information reply */ 544 | /* 545 | * icmp6 namelookup 546 | */ 547 | 548 | struct icmp6_namelookup { 549 | struct icmp6_hdr icmp6_nl_hdr; 550 | uint8_t icmp6_nl_nonce[8]; 551 | int32_t icmp6_nl_ttl; 552 | #if 0 553 | uint8_t icmp6_nl_len; 554 | uint8_t icmp6_nl_name[3]; 555 | #endif 556 | /* could be followed by options */ 557 | } __attribute__ ((__packed__)); 558 | 559 | /* 560 | * icmp6 node information 561 | */ 562 | struct icmp6_nodeinfo { 563 | struct icmp6_hdr icmp6_ni_hdr; 564 | uint8_t icmp6_ni_nonce[8]; 565 | /* could be followed by reply data */ 566 | } __attribute__ ((__packed__)); 567 | 568 | #define ni_type icmp6_ni_hdr.icmp6_type 569 | #define ni_code icmp6_ni_hdr.icmp6_code 570 | #define ni_cksum icmp6_ni_hdr.icmp6_cksum 571 | #define ni_qtype icmp6_ni_hdr.icmp6_data16[0] 572 | #define ni_flags icmp6_ni_hdr.icmp6_data16[1] 573 | 574 | #define NI_QTYPE_NOOP 0 /* NOOP */ 575 | #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */ 576 | #define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ 577 | #define NI_QTYPE_DNSNAME 2 /* DNS Name */ 578 | #define NI_QTYPE_NODEADDR 3 /* Node Addresses */ 579 | #define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ 580 | 581 | #if __BYTE_ORDER == __BIG_ENDIAN 582 | #define NI_SUPTYPE_FLAG_COMPRESS 0x1 583 | #define NI_FQDN_FLAG_VALIDTTL 0x1 584 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 585 | #define NI_SUPTYPE_FLAG_COMPRESS 0x0100 586 | #define NI_FQDN_FLAG_VALIDTTL 0x0100 587 | #endif 588 | 589 | #if __BYTE_ORDER == __BIG_ENDIAN 590 | #define NI_NODEADDR_FLAG_TRUNCATE 0x1 591 | #define NI_NODEADDR_FLAG_ALL 0x2 592 | #define NI_NODEADDR_FLAG_COMPAT 0x4 593 | #define NI_NODEADDR_FLAG_LINKLOCAL 0x8 594 | #define NI_NODEADDR_FLAG_SITELOCAL 0x10 595 | #define NI_NODEADDR_FLAG_GLOBAL 0x20 596 | #define NI_NODEADDR_FLAG_ANYCAST 0x40 /* just experimental. not in spec */ 597 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 598 | #define NI_NODEADDR_FLAG_TRUNCATE 0x0100 599 | #define NI_NODEADDR_FLAG_ALL 0x0200 600 | #define NI_NODEADDR_FLAG_COMPAT 0x0400 601 | #define NI_NODEADDR_FLAG_LINKLOCAL 0x0800 602 | #define NI_NODEADDR_FLAG_SITELOCAL 0x1000 603 | #define NI_NODEADDR_FLAG_GLOBAL 0x2000 604 | #define NI_NODEADDR_FLAG_ANYCAST 0x4000 /* just experimental. not in spec */ 605 | #endif 606 | 607 | struct ni_reply_fqdn { 608 | uint32_t ni_fqdn_ttl; /* TTL */ 609 | uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */ 610 | uint8_t ni_fqdn_name[3]; /* XXX: alignment */ 611 | } __attribute__ ((__packed__)); 612 | 613 | #endif 614 | 615 | 616 | struct ni_reply_ip6 { 617 | uint32_t ni_ip6_ttl; /* TTL */ 618 | struct in6_addr ip6; /* IPv6 address */ 619 | } __attribute__ ((__packed__)); 620 | 621 | 622 | struct ni_reply_ip { 623 | uint32_t ni_ip_ttl; /* TTL */ 624 | struct in_addr ip; /* IPv6 address */ 625 | } __attribute__ ((__packed__)); 626 | 627 | struct ni_reply_name { 628 | uint32_t ni_name_ttl; /* TTL */ 629 | unsigned char ni_name_name; /* IPv6 address */ 630 | } __attribute__ ((__packed__)); 631 | 632 | 633 | /* ICMPv6 Types/Codes not defined in some OSes */ 634 | #ifndef ICMP6_DST_UNREACH_FAILEDPOLICY 635 | #define ICMP6_DST_UNREACH_FAILEDPOLICY 5 636 | #endif 637 | 638 | #ifndef ICMP6_DST_UNREACH_REJECTROUTE 639 | #define ICMP6_DST_UNREACH_REJECTROUTE 6 640 | #endif 641 | 642 | 643 | struct packet{ 644 | unsigned char *link; 645 | unsigned char *ipv6; 646 | unsigned char *upper; 647 | unsigned long maxsize; 648 | }; 649 | 650 | struct iface_data{ 651 | char iface[IFACE_LENGTH]; 652 | unsigned char iface_f; 653 | pcap_t *pfd; 654 | int ifindex; 655 | unsigned char ifindex_f; 656 | struct iface_list iflist; 657 | unsigned int type; 658 | unsigned int flags; 659 | int fd; 660 | unsigned int pending_write_f; 661 | void *pending_write_data; 662 | unsigned int pending_write_size; 663 | fd_set *rset; 664 | fd_set *wset; 665 | fd_set *eset; 666 | unsigned int write_errors; 667 | struct ether_addr ether; 668 | unsigned int ether_flag; 669 | unsigned int linkhsize; 670 | unsigned int max_packet_size; 671 | struct in6_addr ip6_local; 672 | unsigned int ip6_local_flag; 673 | struct prefix_list ip6_global; 674 | unsigned int ip6_global_flag; 675 | struct in6_addr router_ip6; 676 | struct ether_addr router_ether; 677 | struct prefix_list prefix_ac; 678 | struct prefix_list prefix_ol; 679 | unsigned int local_retrans; 680 | unsigned int local_timeout; 681 | unsigned int mtu; 682 | struct ether_addr hsrcaddr; 683 | unsigned int hsrcaddr_f; 684 | struct ether_addr hdstaddr; 685 | unsigned int hdstaddr_f; 686 | struct in_addr srcaddr; 687 | unsigned int src_f; /* XXX Set when a source address has been selected (even if automatically) */ 688 | unsigned int srcaddr_f; 689 | unsigned char srcpreflen; 690 | unsigned char srcprefix_f; 691 | struct in_addr dstaddr; 692 | unsigned int dstaddr_f; 693 | unsigned int verbose_f; 694 | unsigned char listen_f; 695 | unsigned char fragh_f; 696 | 697 | /* XXX 698 | The next four variables are kind of a duplicate of router_ip6 and router_ether above. 699 | May remove them at some point 700 | */ 701 | 702 | struct in6_addr nhaddr; 703 | unsigned char nhaddr_f; 704 | struct ether_addr nhhaddr; 705 | unsigned char nhhaddr_f; 706 | int nhifindex; 707 | unsigned char nhifindex_f; 708 | char nhiface[IFACE_LENGTH]; 709 | unsigned char nh_f; 710 | uint16_t srcport; 711 | uint16_t dstport; 712 | char srcport_f; 713 | char dstport_f; 714 | }; 715 | 716 | 717 | #ifdef __linux__ 718 | /* Consulting the routing table */ 719 | #define MAX_NLPAYLOAD 1024 720 | #else 721 | #define MAX_RTPAYLOAD 1024 722 | #endif 723 | 724 | #if defined(__linux__) 725 | 726 | #define SLL_ADDRLEN 0 727 | 728 | struct sll_linux{ 729 | uint16_t sll_pkttype; /* packet type */ 730 | uint16_t sll_hatype; /* link-layer address type */ 731 | uint16_t sll_halen; /* link-layer address length */ 732 | uint8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ 733 | uint16_t sll_protocol; /* protocol */ 734 | } __attribute__ ((__packed__)); 735 | #endif 736 | 737 | 738 | struct next_hop{ 739 | struct in6_addr srcaddr; 740 | unsigned char srcaddr_f; 741 | struct in6_addr dstaddr; 742 | unsigned char dstaddr_f; 743 | struct in6_addr nhaddr; 744 | unsigned char nhaddr_f; 745 | struct ether_addr nhhaddr; 746 | unsigned char nhhaddr_f; 747 | int ifindex; 748 | unsigned char ifindex_f; 749 | }; 750 | 751 | 752 | /* Flags that specify what the load_dst_and_pcap() function should do */ 753 | #define LOAD_PCAP_ONLY 0x01 754 | #define LOAD_SRC_NXT_HOP 0x02 755 | 756 | /* Constants to signal special interface types */ 757 | #define IFACE_LOOPBACK 1 758 | #define IFACE_TUNNEL 2 759 | 760 | #ifndef SA_SIZE 761 | #if defined(__APPLE__) 762 | #define SA_SIZE(sa) \ 763 | ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ 764 | sizeof(long) : \ 765 | ((struct sockaddr *)(sa))->sa_len ) 766 | #elif defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) 767 | #define SA_SIZE(sa) \ 768 | ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ 769 | sizeof(long) : \ 770 | 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) 771 | #else 772 | #define SA_SIZE(sa) sizeof(struct sockaddr) 773 | #endif 774 | #endif 775 | 776 | 777 | #define MAX_JSON_ITEMS 150 778 | 779 | struct json{ 780 | unsigned int nitem; 781 | unsigned int maxitems; /* MAX_ITEMS */ 782 | char *key[MAX_JSON_ITEMS]; 783 | unsigned int key_l[MAX_JSON_ITEMS]; 784 | char *value[MAX_JSON_ITEMS]; 785 | unsigned int value_l[MAX_JSON_ITEMS]; 786 | }; 787 | 788 | 789 | struct json_value{ 790 | char *value; 791 | unsigned int len; 792 | }; 793 | 794 | 795 | #define IP_LIMITED_MULTICAST "255.255.255.255" 796 | #define NULL_STRING "" 797 | #define TP_LINK_SMART_PORT 9999 798 | /* XXX Should use different constant */ 799 | #define MAX_TP_COMMAND_LENGTH 10000 800 | #define TP_LINK_IP_CAMERA_TDDP_PORT 1068 801 | 802 | 803 | int init_iface_data(struct iface_data *); 804 | void debug_print_iflist(struct iface_list *); 805 | int ether_ntop(const struct ether_addr *, char *, size_t); 806 | int ether_pton(const char *, struct ether_addr *, unsigned int); 807 | void *find_iface_by_index(struct iface_list *, int); 808 | void *find_iface_by_name(struct iface_list *, char *); 809 | void *find_iface_by_addr(struct iface_list *, void *, sa_family_t); 810 | void *find_v4addr(struct iface_list *); 811 | void *find_v4addr_for_iface(struct iface_list *, char *); 812 | int get_local_addrs(struct iface_data *); 813 | int is_ip_in_prefix_list(struct in_addr *, struct prefixv4_list *); 814 | int is_ip6_in_prefix_list(struct in6_addr *, struct prefix_list *); 815 | int is_time_elapsed(struct timeval *, struct timeval *, unsigned long); 816 | void release_privileges(void); 817 | size_t Strnlen(const char *, size_t); 818 | struct timeval timeval_sub(struct timeval *, struct timeval *); 819 | float time_diff_ms(struct timeval *, struct timeval *); 820 | void tp_link_crypt(unsigned char *, size_t); 821 | void tp_link_decrypt(unsigned char *, size_t); 822 | void dump_hex(void *, size_t); 823 | void dump_text(void* ptr, size_t s); 824 | 825 | 826 | 827 | 828 | int json_free_struct(struct json *); 829 | void json_print_objects(struct json *); 830 | unsigned int json_get_value(struct json *, struct json_value *, char *); 831 | struct json * json_get_objects(char *, unsigned int); 832 | unsigned int json_add_item(struct json *, char *, unsigned int, char *, unsigned int); 833 | struct json * json_alloc_struct(void); 834 | int is_valid_json_string(char *, unsigned int); 835 | unsigned int json_remove_quotes(struct json *); 836 | uint16_t in_chksum(uint16_t *, size_t); 837 | 838 | 839 | --------------------------------------------------------------------------------