mirror of
				https://github.com/xcat2/xNBA.git
				synced 2025-10-31 19:32:34 +00:00 
			
		
		
		
	NMB packets are so similar to DNS packets; we may as well add NMB as a
name resolution method.
This commit is contained in:
		
							
								
								
									
										22
									
								
								src/include/nmb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/include/nmb.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #ifndef NMB_H | ||||
| #define NMB_H | ||||
|  | ||||
| #include "dns.h" | ||||
|  | ||||
| /* | ||||
|  * NetBIOS name query packets are basically the same as DNS packets, | ||||
|  * though the resource record format is different. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define DNS_TYPE_NB		0x20 | ||||
| #define DNS_FLAG_BROADCAST	( 0x01 << 4 ) | ||||
| #define NBNS_UDP_PORT		137 | ||||
|  | ||||
| struct dns_rr_info_nb { | ||||
| 	struct dns_rr_info; | ||||
| 	uint16_t	nb_flags; | ||||
| 	struct in_addr	nb_address; | ||||
| } __attribute__ (( packed )); | ||||
|  | ||||
| #endif /* NMB_H */ | ||||
							
								
								
									
										103
									
								
								src/proto/nmb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/proto/nmb.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| #include "resolv.h" | ||||
| #include "string.h" | ||||
| #include "dns.h" | ||||
| #include "nic.h" | ||||
| #include "nmb.h" | ||||
|  | ||||
| /* | ||||
|  * Convert a standard NUL-terminated string to an NBNS query name. | ||||
|  * | ||||
|  * Returns a pointer to the character following the constructed NBNS | ||||
|  * query name. | ||||
|  * | ||||
|  */ | ||||
| static inline char * nbns_make_name ( char *dest, const char *name ) { | ||||
| 	char nb_name[16]; | ||||
| 	char c; | ||||
| 	int i; | ||||
|  | ||||
| 	*(dest++) = 32; /* Length is always 32 */ | ||||
|  | ||||
| 	/* Name encoding is as follows: pad the name with spaces to | ||||
| 	 * length 15, and add a NUL.  Take this 16-byte string, split | ||||
| 	 * it into nibbles and add 0x41 to each nibble to form a byte | ||||
| 	 * of the resulting name string. | ||||
| 	 */ | ||||
| 	memset ( nb_name, ' ', 15 ); | ||||
| 	nb_name[15] = '\0'; | ||||
| 	memcpy ( nb_name, name, strlen ( name ) ); /* Do not copy NUL */ | ||||
| 	for ( i = 0 ; i < 16 ; i++ ) { | ||||
| 		c = nb_name[i]; | ||||
| 		*( ( ( uint16_t * ) dest ) ++ ) =  | ||||
| 			htons ( ( ( c | ( c << 4 ) ) & 0x0f0f ) + 0x4141 ); | ||||
| 	} | ||||
|  | ||||
| 	*(dest++) = 0; /* Terminating 0-length name component */ | ||||
| 	return dest; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Resolve a name using NMB | ||||
|  * | ||||
|  */ | ||||
| static int nmb_resolv ( struct in_addr *addr, const char *name ) { | ||||
| 	struct dns_query query; | ||||
| 	struct dns_query_info *query_info; | ||||
| 	struct dns_header *reply; | ||||
| 	struct dns_rr_info *rr_info; | ||||
| 	struct dns_rr_info_nb *rr_info_nb; | ||||
| 	struct sockaddr_in nameserver; | ||||
|  | ||||
| 	DBG ( "NMB resolving %s\n", name ); | ||||
|  | ||||
| 	/* Set up the query data */ | ||||
| 	nameserver.sin_addr.s_addr = IP_BROADCAST; | ||||
| 	nameserver.sin_port = NBNS_UDP_PORT; | ||||
| 	memset ( &query, 0, sizeof ( query ) ); | ||||
| 	query.dns.id = htons ( 1 ); | ||||
| 	query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY | | ||||
| 				  DNS_FLAG_RD | DNS_FLAG_BROADCAST ); | ||||
| 	query.dns.qdcount = htons ( 1 ); | ||||
| 	query_info = ( void * )	nbns_make_name ( query.payload, name ); | ||||
| 	query_info->qtype = htons ( DNS_TYPE_NB ); | ||||
| 	query_info->qclass = htons ( DNS_CLASS_IN ); | ||||
|  | ||||
| 	/* Issue query, wait for reply */ | ||||
| 	reply = dns_query ( &query, | ||||
| 			    ( ( ( char * ) query_info ) | ||||
| 			      + sizeof ( *query_info ) | ||||
| 			      - ( ( char * ) &query ) ), | ||||
| 			    &nameserver ); | ||||
| 	if ( ! reply ) { | ||||
| 		DBG ( "NMB got no response via %@ (port %d)\n", | ||||
| 		      nameserver.sin_addr.s_addr, | ||||
| 		      nameserver.sin_port ); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Search through response for useful answers. */ | ||||
| 	rr_info = dns_find_rr ( &query, reply ); | ||||
| 	if ( ! rr_info ) { | ||||
| 		DBG ( "NMB got invalid response\n" ); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Check type of response */ | ||||
| 	if ( ntohs ( rr_info->type ) != DNS_TYPE_NB ) { | ||||
| 		DBG ( "NMB got answer type %hx (wanted %hx)\n", | ||||
| 		      ntohs ( rr_info->type ), DNS_TYPE_NB ); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Read response */ | ||||
| 	rr_info_nb = ( struct dns_rr_info_nb * ) rr_info; | ||||
| 	*addr = rr_info_nb->nb_address; | ||||
| 	DBG ( "NMB found address %@\n", addr->s_addr ); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static struct resolver nmb_resolver __resolver = { | ||||
| 	.name = "NMB", | ||||
| 	.resolv = nmb_resolv, | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user