mirror of
				https://bitbucket.org/ohhara/ohmulticastvideoscanner.git
				synced 2025-10-30 18:07:54 +00:00 
			
		
		
		
	Find multicast UDP port list.
This commit is contained in:
		
							parent
							
								
									7ad2c4b910
								
							
						
					
					
						commit
						106a251f17
					
				
							
								
								
									
										160
									
								
								omvs_main.c
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								omvs_main.c
									
									
									
									
									
								
							| @ -1,10 +1,12 @@ | ||||
| #include <string.h> | ||||
| #include <pcap.h> | ||||
| #include <pcap/pcap.h> | ||||
| #include <glib.h> | ||||
| #include <glib/gstdio.h> | ||||
| #include <gio/gio.h> | ||||
| #include <gst/gst.h> | ||||
| 
 | ||||
| #define _OMVS_IPPROTO_UDP 17 | ||||
| 
 | ||||
| static gint _omvs_net_dev_idx; | ||||
| static gboolean _omvs_list_devs; | ||||
| static gchar *_omvs_outdir = "omvs_out"; | ||||
| @ -36,14 +38,43 @@ static GOptionEntry _omvs_entries[] = | ||||
|   { NULL } | ||||
| }; | ||||
| 
 | ||||
| typedef struct _OMVSPort { | ||||
|   gint port; | ||||
|   gint type; | ||||
| } OMVSPort; | ||||
| typedef struct _OMVSEthHdr { | ||||
|   guint8 ether_dhost[6]; | ||||
|   guint8 ether_shost[6]; | ||||
|   guint16 ether_type; | ||||
| } __attribute__((packed)) OMVSEthHdr; | ||||
| 
 | ||||
| typedef struct _OMVSIPHdr { | ||||
| #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||||
|   guint ihl:4; | ||||
|   guint version:4; | ||||
| #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | ||||
|   guint version:4; | ||||
|   guint ihl:4; | ||||
| #else | ||||
| #error "endian error" | ||||
| #endif | ||||
|   guint8 tos; | ||||
|   guint16 tot_len; | ||||
|   guint16 id; | ||||
|   guint16 frag_off; | ||||
|   guint8 ttl; | ||||
|   guint8 protocol; | ||||
|   guint16 check; | ||||
|   guint32 saddr; | ||||
|   guint32 daddr; | ||||
| } OMVSIPHdr; | ||||
| 
 | ||||
| typedef struct _OMVSUDPHdr { | ||||
|   guint16 uh_sport; | ||||
|   guint16 uh_dport; | ||||
|   guint16 uh_ulen; | ||||
|   guint16 uh_sum; | ||||
| } OMVSUDPHdr; | ||||
| 
 | ||||
| typedef struct _OMVSIPAddr { | ||||
|   guint32 addr; | ||||
|   OMVSPort *ports; | ||||
|   guint16 *ports; | ||||
|   gint num_ports; | ||||
| } OMVSIPAddr; | ||||
| 
 | ||||
| @ -116,6 +147,10 @@ static gpointer _omvs_start_scan_job(gpointer data) { | ||||
|   GSocketAddress *socket_address; | ||||
|   GInetAddress *inet_address; | ||||
|   gint i; | ||||
|   pcap_t *pcap; | ||||
|   gchar errbuf[PCAP_ERRBUF_SIZE]; | ||||
|   const guint8 *packet; | ||||
|   struct pcap_pkthdr *header; | ||||
| 
 | ||||
|   scanner = (OMVSScanner *)data; | ||||
| 
 | ||||
| @ -136,15 +171,35 @@ static gpointer _omvs_start_scan_job(gpointer data) { | ||||
|     goto finish_return2; | ||||
|   } | ||||
| 
 | ||||
|   pcap = pcap_open_live(_omvs_net_dev_names[_omvs_net_dev_idx], | ||||
|     sizeof(OMVSEthHdr) + sizeof(OMVSIPHdr) + sizeof(OMVSUDPHdr), | ||||
|     TRUE, 500, errbuf); | ||||
|   if (pcap == NULL) { | ||||
|     g_printerr("[%p] can't open pcap: %s\n", (void *)g_thread_self(), errbuf); | ||||
|     goto finish_return2; | ||||
|   } | ||||
|   if (pcap_datalink(pcap) != DLT_EN10MB) { | ||||
|     g_printerr("[%p] %s is not ethernet\n", (void *)g_thread_self(), | ||||
|       _omvs_net_dev_names[_omvs_net_dev_idx]); | ||||
|     goto finish_return3; | ||||
|   } | ||||
| 
 | ||||
|   for (i = 0; i < scanner->num_ipaddrs; i++) { | ||||
|     OMVSIPAddr *o_ipaddr; | ||||
|     guint8 addr[4]; | ||||
|     guint32 naddr; | ||||
|     gchar *addr_str; | ||||
|     GInetAddress *group_address; | ||||
|     gint64 time1, time2; | ||||
|     gint j; | ||||
| 
 | ||||
|     addr[0] = (guint8)((scanner->ipaddrs[i].addr >> 24) & 0xff); | ||||
|     addr[1] = (guint8)((scanner->ipaddrs[i].addr >> 16) & 0xff); | ||||
|     addr[2] = (guint8)((scanner->ipaddrs[i].addr >> 8) & 0xff); | ||||
|     addr[3] = (guint8)((scanner->ipaddrs[i].addr >> 0) & 0xff); | ||||
|     o_ipaddr = &scanner->ipaddrs[i]; | ||||
| 
 | ||||
|     naddr = g_htonl(o_ipaddr->addr); | ||||
|     addr[0] = (guint8)((o_ipaddr->addr >> 24) & 0xff); | ||||
|     addr[1] = (guint8)((o_ipaddr->addr >> 16) & 0xff); | ||||
|     addr[2] = (guint8)((o_ipaddr->addr >> 8) & 0xff); | ||||
|     addr[3] = (guint8)((o_ipaddr->addr >> 0) & 0xff); | ||||
| 
 | ||||
|     addr_str = | ||||
|       g_strdup_printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); | ||||
| @ -159,7 +214,86 @@ static gpointer _omvs_start_scan_job(gpointer data) { | ||||
|         addr_str, error->message); | ||||
|     } | ||||
| 
 | ||||
|     g_usleep(_omvs_timeout * 1000); | ||||
|     time1 = g_get_monotonic_time(); | ||||
|     for (;;) { | ||||
|       gint ret; | ||||
|       guint caplen; | ||||
|       OMVSIPHdr *ip; | ||||
|       OMVSUDPHdr *udp; | ||||
|       guint ip_hdr_len; | ||||
|       gint udp_port; | ||||
|       gboolean is_udp_port_found; | ||||
| 
 | ||||
|       ret = pcap_next_ex(pcap, &header, &packet); | ||||
| 
 | ||||
|       if (ret < 0) { | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       time2 = g_get_monotonic_time(); | ||||
|       if (time2 - time1 > (gint64)((gint64)_omvs_timeout * 1000)) { | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       if (ret == 0) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       caplen = header->caplen; | ||||
| 
 | ||||
|       if (caplen < sizeof(OMVSEthHdr)) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       packet += sizeof(OMVSEthHdr); | ||||
|       caplen -= sizeof(OMVSEthHdr); | ||||
|       if (caplen < sizeof(OMVSIPHdr)) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       ip = (OMVSIPHdr *)packet; | ||||
|       ip_hdr_len = ip->ihl * 4; | ||||
|       if (caplen < ip_hdr_len) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       if (ip->protocol != _OMVS_IPPROTO_UDP) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       if (naddr != ip->daddr) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       packet += ip_hdr_len; | ||||
|       caplen -= ip_hdr_len; | ||||
| 
 | ||||
|       if (caplen < sizeof(OMVSUDPHdr)) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       udp = (OMVSUDPHdr *)packet; | ||||
|       udp_port = g_ntohs(udp->uh_dport); | ||||
| 
 | ||||
|       is_udp_port_found = FALSE; | ||||
|       for (j = 0; j < o_ipaddr->num_ports; j++) { | ||||
|         if (o_ipaddr->ports[j] == udp_port) { | ||||
|           is_udp_port_found = TRUE; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       if (!is_udp_port_found) { | ||||
|         o_ipaddr->ports = g_realloc(o_ipaddr->ports, | ||||
|           (o_ipaddr->num_ports + 1) * sizeof(guint16)); | ||||
|         o_ipaddr->ports[o_ipaddr->num_ports] = udp_port; | ||||
|         o_ipaddr->num_ports++; | ||||
|         if (_omvs_verbose) { | ||||
|           g_print("[%p] found udp://%s:%d\n", (void *)g_thread_self(), | ||||
|             addr_str, udp_port); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (_omvs_verbose) { | ||||
|       g_print("[%p] finish scanning %s\n", (void *)g_thread_self(), addr_str); | ||||
| @ -175,6 +309,8 @@ static gpointer _omvs_start_scan_job(gpointer data) { | ||||
|     g_usleep(_omvs_sleep * 1000); | ||||
|   } | ||||
| 
 | ||||
| finish_return3: | ||||
|   pcap_close(pcap); | ||||
| finish_return2: | ||||
|   g_object_unref(socket_address); | ||||
|   g_object_unref(socket); | ||||
| @ -256,7 +392,7 @@ int main(int argc, char *argv[]) { | ||||
|     goto finish_return; | ||||
|   } | ||||
| 
 | ||||
|   if (argc < 2) { | ||||
|   if (argc < 2 || _omvs_net_dev_idx >= _omvs_num_net_devs) { | ||||
|     gchar *help_msg; | ||||
|     help_msg = g_option_context_get_help(context, TRUE, NULL); | ||||
|     g_print("%s", help_msg); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user