Просмотр исходного кода

NMB packets are so similar to DNS packets; we may as well add NMB as a

name resolution method.
tags/v0.9.3
Michael Brown 19 лет назад
Родитель
Сommit
3ae7a3d1f0
2 измененных файлов: 125 добавлений и 0 удалений
  1. 22
    0
      src/include/nmb.h
  2. 103
    0
      src/proto/nmb.c

+ 22
- 0
src/include/nmb.h Просмотреть файл

@@ -0,0 +1,22 @@
1
+#ifndef NMB_H
2
+#define NMB_H
3
+
4
+#include "dns.h"
5
+
6
+/*
7
+ * NetBIOS name query packets are basically the same as DNS packets,
8
+ * though the resource record format is different.
9
+ *
10
+ */
11
+
12
+#define DNS_TYPE_NB		0x20
13
+#define DNS_FLAG_BROADCAST	( 0x01 << 4 )
14
+#define NBNS_UDP_PORT		137
15
+
16
+struct dns_rr_info_nb {
17
+	struct dns_rr_info;
18
+	uint16_t	nb_flags;
19
+	struct in_addr	nb_address;
20
+} __attribute__ (( packed ));
21
+
22
+#endif /* NMB_H */

+ 103
- 0
src/proto/nmb.c Просмотреть файл

@@ -0,0 +1,103 @@
1
+#include "resolv.h"
2
+#include "string.h"
3
+#include "dns.h"
4
+#include "nic.h"
5
+#include "nmb.h"
6
+
7
+/*
8
+ * Convert a standard NUL-terminated string to an NBNS query name.
9
+ *
10
+ * Returns a pointer to the character following the constructed NBNS
11
+ * query name.
12
+ *
13
+ */
14
+static inline char * nbns_make_name ( char *dest, const char *name ) {
15
+	char nb_name[16];
16
+	char c;
17
+	int i;
18
+
19
+	*(dest++) = 32; /* Length is always 32 */
20
+
21
+	/* Name encoding is as follows: pad the name with spaces to
22
+	 * length 15, and add a NUL.  Take this 16-byte string, split
23
+	 * it into nibbles and add 0x41 to each nibble to form a byte
24
+	 * of the resulting name string.
25
+	 */
26
+	memset ( nb_name, ' ', 15 );
27
+	nb_name[15] = '\0';
28
+	memcpy ( nb_name, name, strlen ( name ) ); /* Do not copy NUL */
29
+	for ( i = 0 ; i < 16 ; i++ ) {
30
+		c = nb_name[i];
31
+		*( ( ( uint16_t * ) dest ) ++ ) = 
32
+			htons ( ( ( c | ( c << 4 ) ) & 0x0f0f ) + 0x4141 );
33
+	}
34
+
35
+	*(dest++) = 0; /* Terminating 0-length name component */
36
+	return dest;
37
+}
38
+
39
+/*
40
+ * Resolve a name using NMB
41
+ *
42
+ */
43
+static int nmb_resolv ( struct in_addr *addr, const char *name ) {
44
+	struct dns_query query;
45
+	struct dns_query_info *query_info;
46
+	struct dns_header *reply;
47
+	struct dns_rr_info *rr_info;
48
+	struct dns_rr_info_nb *rr_info_nb;
49
+	struct sockaddr_in nameserver;
50
+
51
+	DBG ( "NMB resolving %s\n", name );
52
+
53
+	/* Set up the query data */
54
+	nameserver.sin_addr.s_addr = IP_BROADCAST;
55
+	nameserver.sin_port = NBNS_UDP_PORT;
56
+	memset ( &query, 0, sizeof ( query ) );
57
+	query.dns.id = htons ( 1 );
58
+	query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
59
+				  DNS_FLAG_RD | DNS_FLAG_BROADCAST );
60
+	query.dns.qdcount = htons ( 1 );
61
+	query_info = ( void * )	nbns_make_name ( query.payload, name );
62
+	query_info->qtype = htons ( DNS_TYPE_NB );
63
+	query_info->qclass = htons ( DNS_CLASS_IN );
64
+
65
+	/* Issue query, wait for reply */
66
+	reply = dns_query ( &query,
67
+			    ( ( ( char * ) query_info )
68
+			      + sizeof ( *query_info )
69
+			      - ( ( char * ) &query ) ),
70
+			    &nameserver );
71
+	if ( ! reply ) {
72
+		DBG ( "NMB got no response via %@ (port %d)\n",
73
+		      nameserver.sin_addr.s_addr,
74
+		      nameserver.sin_port );
75
+		return 0;
76
+	}
77
+
78
+	/* Search through response for useful answers. */
79
+	rr_info = dns_find_rr ( &query, reply );
80
+	if ( ! rr_info ) {
81
+		DBG ( "NMB got invalid response\n" );
82
+		return 0;
83
+	}
84
+
85
+	/* Check type of response */
86
+	if ( ntohs ( rr_info->type ) != DNS_TYPE_NB ) {
87
+		DBG ( "NMB got answer type %hx (wanted %hx)\n",
88
+		      ntohs ( rr_info->type ), DNS_TYPE_NB );
89
+		return 0;
90
+	}
91
+
92
+	/* Read response */
93
+	rr_info_nb = ( struct dns_rr_info_nb * ) rr_info;
94
+	*addr = rr_info_nb->nb_address;
95
+	DBG ( "NMB found address %@\n", addr->s_addr );
96
+
97
+	return 1;
98
+}
99
+
100
+static struct resolver nmb_resolver __resolver = {
101
+	.name = "NMB",
102
+	.resolv = nmb_resolv,
103
+};

Загрузка…
Отмена
Сохранить