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 <string.h> | ||||||
| #include <pcap.h> | #include <pcap/pcap.h> | ||||||
| #include <glib.h> | #include <glib.h> | ||||||
| #include <glib/gstdio.h> | #include <glib/gstdio.h> | ||||||
| #include <gio/gio.h> | #include <gio/gio.h> | ||||||
| #include <gst/gst.h> | #include <gst/gst.h> | ||||||
| 
 | 
 | ||||||
|  | #define _OMVS_IPPROTO_UDP 17 | ||||||
|  | 
 | ||||||
| static gint _omvs_net_dev_idx; | static gint _omvs_net_dev_idx; | ||||||
| static gboolean _omvs_list_devs; | static gboolean _omvs_list_devs; | ||||||
| static gchar *_omvs_outdir = "omvs_out"; | static gchar *_omvs_outdir = "omvs_out"; | ||||||
| @ -36,14 +38,43 @@ static GOptionEntry _omvs_entries[] = | |||||||
|   { NULL } |   { NULL } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct _OMVSPort { | typedef struct _OMVSEthHdr { | ||||||
|   gint port; |   guint8 ether_dhost[6]; | ||||||
|   gint type; |   guint8 ether_shost[6]; | ||||||
| } OMVSPort; |   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 { | typedef struct _OMVSIPAddr { | ||||||
|   guint32 addr; |   guint32 addr; | ||||||
|   OMVSPort *ports; |   guint16 *ports; | ||||||
|   gint num_ports; |   gint num_ports; | ||||||
| } OMVSIPAddr; | } OMVSIPAddr; | ||||||
| 
 | 
 | ||||||
| @ -116,6 +147,10 @@ static gpointer _omvs_start_scan_job(gpointer data) { | |||||||
|   GSocketAddress *socket_address; |   GSocketAddress *socket_address; | ||||||
|   GInetAddress *inet_address; |   GInetAddress *inet_address; | ||||||
|   gint i; |   gint i; | ||||||
|  |   pcap_t *pcap; | ||||||
|  |   gchar errbuf[PCAP_ERRBUF_SIZE]; | ||||||
|  |   const guint8 *packet; | ||||||
|  |   struct pcap_pkthdr *header; | ||||||
| 
 | 
 | ||||||
|   scanner = (OMVSScanner *)data; |   scanner = (OMVSScanner *)data; | ||||||
| 
 | 
 | ||||||
| @ -136,15 +171,35 @@ static gpointer _omvs_start_scan_job(gpointer data) { | |||||||
|     goto finish_return2; |     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++) { |   for (i = 0; i < scanner->num_ipaddrs; i++) { | ||||||
|  |     OMVSIPAddr *o_ipaddr; | ||||||
|     guint8 addr[4]; |     guint8 addr[4]; | ||||||
|  |     guint32 naddr; | ||||||
|     gchar *addr_str; |     gchar *addr_str; | ||||||
|     GInetAddress *group_address; |     GInetAddress *group_address; | ||||||
|  |     gint64 time1, time2; | ||||||
|  |     gint j; | ||||||
| 
 | 
 | ||||||
|     addr[0] = (guint8)((scanner->ipaddrs[i].addr >> 24) & 0xff); |     o_ipaddr = &scanner->ipaddrs[i]; | ||||||
|     addr[1] = (guint8)((scanner->ipaddrs[i].addr >> 16) & 0xff); | 
 | ||||||
|     addr[2] = (guint8)((scanner->ipaddrs[i].addr >> 8) & 0xff); |     naddr = g_htonl(o_ipaddr->addr); | ||||||
|     addr[3] = (guint8)((scanner->ipaddrs[i].addr >> 0) & 0xff); |     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 = |     addr_str = | ||||||
|       g_strdup_printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); |       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); |         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) { |     if (_omvs_verbose) { | ||||||
|       g_print("[%p] finish scanning %s\n", (void *)g_thread_self(), addr_str); |       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); |     g_usleep(_omvs_sleep * 1000); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | finish_return3: | ||||||
|  |   pcap_close(pcap); | ||||||
| finish_return2: | finish_return2: | ||||||
|   g_object_unref(socket_address); |   g_object_unref(socket_address); | ||||||
|   g_object_unref(socket); |   g_object_unref(socket); | ||||||
| @ -256,7 +392,7 @@ int main(int argc, char *argv[]) { | |||||||
|     goto finish_return; |     goto finish_return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (argc < 2) { |   if (argc < 2 || _omvs_net_dev_idx >= _omvs_num_net_devs) { | ||||||
|     gchar *help_msg; |     gchar *help_msg; | ||||||
|     help_msg = g_option_context_get_help(context, TRUE, NULL); |     help_msg = g_option_context_get_help(context, TRUE, NULL); | ||||||
|     g_print("%s", help_msg); |     g_print("%s", help_msg); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user