1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | handle unexpected packets
|
---|
4 | Copyright (C) Andrew Tridgell 2000
|
---|
5 |
|
---|
6 | This program is free software; you can redistribute it and/or modify
|
---|
7 | it under the terms of the GNU General Public License as published by
|
---|
8 | the Free Software Foundation; either version 3 of the License, or
|
---|
9 | (at your option) any later version.
|
---|
10 |
|
---|
11 | This program is distributed in the hope that it will be useful,
|
---|
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | GNU General Public License for more details.
|
---|
15 |
|
---|
16 | You should have received a copy of the GNU General Public License
|
---|
17 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
18 |
|
---|
19 | */
|
---|
20 |
|
---|
21 | #include "includes.h"
|
---|
22 |
|
---|
23 | static TDB_CONTEXT *tdbd = NULL;
|
---|
24 |
|
---|
25 | /* the key type used in the unexpected packet database */
|
---|
26 | struct unexpected_key {
|
---|
27 | enum packet_type packet_type;
|
---|
28 | time_t timestamp;
|
---|
29 | int count;
|
---|
30 | };
|
---|
31 |
|
---|
32 | /****************************************************************************
|
---|
33 | All unexpected packets are passed in here, to be stored in a unexpected
|
---|
34 | packet database. This allows nmblookup and other tools to receive packets
|
---|
35 | erroneously sent to the wrong port by broken MS systems.
|
---|
36 | **************************************************************************/
|
---|
37 |
|
---|
38 | void unexpected_packet(struct packet_struct *p)
|
---|
39 | {
|
---|
40 | static int count;
|
---|
41 | TDB_DATA kbuf, dbuf;
|
---|
42 | struct unexpected_key key;
|
---|
43 | char buf[1024];
|
---|
44 | int len=0;
|
---|
45 | uint32_t enc_ip;
|
---|
46 |
|
---|
47 | if (!tdbd) {
|
---|
48 | tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
|
---|
49 | TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
|
---|
50 | O_RDWR | O_CREAT, 0644);
|
---|
51 | if (!tdbd) {
|
---|
52 | DEBUG(0,("Failed to open unexpected.tdb\n"));
|
---|
53 | return;
|
---|
54 | }
|
---|
55 | }
|
---|
56 |
|
---|
57 | memset(buf,'\0',sizeof(buf));
|
---|
58 |
|
---|
59 | /* Encode the ip addr and port. */
|
---|
60 | enc_ip = ntohl(p->ip.s_addr);
|
---|
61 | SIVAL(buf,0,enc_ip);
|
---|
62 | SSVAL(buf,4,p->port);
|
---|
63 |
|
---|
64 | len = build_packet(&buf[6], sizeof(buf)-6, p) + 6;
|
---|
65 |
|
---|
66 | ZERO_STRUCT(key); /* needed for potential alignment */
|
---|
67 |
|
---|
68 | key.packet_type = p->packet_type;
|
---|
69 | key.timestamp = p->timestamp;
|
---|
70 | key.count = count++;
|
---|
71 |
|
---|
72 | kbuf.dptr = (uint8_t *)&key;
|
---|
73 | kbuf.dsize = sizeof(key);
|
---|
74 | dbuf.dptr = (uint8_t *)buf;
|
---|
75 | dbuf.dsize = len;
|
---|
76 |
|
---|
77 | tdb_store(tdbd, kbuf, dbuf, TDB_REPLACE);
|
---|
78 | }
|
---|
79 |
|
---|
80 |
|
---|
81 | static time_t lastt;
|
---|
82 |
|
---|
83 | /****************************************************************************
|
---|
84 | Delete the record if it is too old.
|
---|
85 | **************************************************************************/
|
---|
86 |
|
---|
87 | static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
|
---|
88 | {
|
---|
89 | struct unexpected_key key;
|
---|
90 |
|
---|
91 | if (kbuf.dsize != sizeof(key)) {
|
---|
92 | tdb_delete(ttdb, kbuf);
|
---|
93 | }
|
---|
94 |
|
---|
95 | memcpy(&key, kbuf.dptr, sizeof(key));
|
---|
96 |
|
---|
97 | if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) {
|
---|
98 | tdb_delete(ttdb, kbuf);
|
---|
99 | }
|
---|
100 |
|
---|
101 | return 0;
|
---|
102 | }
|
---|
103 |
|
---|
104 |
|
---|
105 | /****************************************************************************
|
---|
106 | Delete all old unexpected packets.
|
---|
107 | **************************************************************************/
|
---|
108 |
|
---|
109 | void clear_unexpected(time_t t)
|
---|
110 | {
|
---|
111 | if (!tdbd) return;
|
---|
112 |
|
---|
113 | if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
|
---|
114 | return;
|
---|
115 |
|
---|
116 | lastt = t;
|
---|
117 |
|
---|
118 | tdb_traverse(tdbd, traverse_fn, NULL);
|
---|
119 | }
|
---|
120 |
|
---|
121 | struct receive_unexpected_state {
|
---|
122 | struct packet_struct *matched_packet;
|
---|
123 | int match_id;
|
---|
124 | enum packet_type match_type;
|
---|
125 | const char *match_name;
|
---|
126 | };
|
---|
127 |
|
---|
128 | /****************************************************************************
|
---|
129 | tdb traversal fn to find a matching 137 packet.
|
---|
130 | **************************************************************************/
|
---|
131 |
|
---|
132 | static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf,
|
---|
133 | void *private_data)
|
---|
134 | {
|
---|
135 | struct receive_unexpected_state *state =
|
---|
136 | (struct receive_unexpected_state *)private_data;
|
---|
137 | struct unexpected_key key;
|
---|
138 | struct in_addr ip;
|
---|
139 | uint32_t enc_ip;
|
---|
140 | int port;
|
---|
141 | struct packet_struct *p;
|
---|
142 |
|
---|
143 | if (kbuf.dsize != sizeof(key)) {
|
---|
144 | return 0;
|
---|
145 | }
|
---|
146 |
|
---|
147 | memcpy(&key, kbuf.dptr, sizeof(key));
|
---|
148 |
|
---|
149 | if (key.packet_type != state->match_type) return 0;
|
---|
150 |
|
---|
151 | if (dbuf.dsize < 6) {
|
---|
152 | return 0;
|
---|
153 | }
|
---|
154 |
|
---|
155 | /* Decode the ip addr and port. */
|
---|
156 | enc_ip = IVAL(dbuf.dptr,0);
|
---|
157 | ip.s_addr = htonl(enc_ip);
|
---|
158 | port = SVAL(dbuf.dptr,4);
|
---|
159 |
|
---|
160 | p = parse_packet((char *)&dbuf.dptr[6],
|
---|
161 | dbuf.dsize-6,
|
---|
162 | state->match_type,
|
---|
163 | ip,
|
---|
164 | port);
|
---|
165 |
|
---|
166 | if (!p) {
|
---|
167 | return 0;
|
---|
168 | }
|
---|
169 |
|
---|
170 | if ((state->match_type == NMB_PACKET &&
|
---|
171 | p->packet.nmb.header.name_trn_id == state->match_id) ||
|
---|
172 | (state->match_type == DGRAM_PACKET &&
|
---|
173 | match_mailslot_name(p, state->match_name))) {
|
---|
174 | state->matched_packet = p;
|
---|
175 | return -1;
|
---|
176 | }
|
---|
177 |
|
---|
178 | free_packet(p);
|
---|
179 |
|
---|
180 | return 0;
|
---|
181 | }
|
---|
182 |
|
---|
183 | /****************************************************************************
|
---|
184 | Check for a particular packet in the unexpected packet queue.
|
---|
185 | **************************************************************************/
|
---|
186 |
|
---|
187 | struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
|
---|
188 | const char *mailslot_name)
|
---|
189 | {
|
---|
190 | TDB_CONTEXT *tdb2;
|
---|
191 | struct receive_unexpected_state state;
|
---|
192 |
|
---|
193 | tdb2 = tdb_open_log(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0);
|
---|
194 | if (!tdb2) return NULL;
|
---|
195 |
|
---|
196 | state.matched_packet = NULL;
|
---|
197 | state.match_id = id;
|
---|
198 | state.match_type = packet_type;
|
---|
199 | state.match_name = mailslot_name;
|
---|
200 |
|
---|
201 | tdb_traverse(tdb2, traverse_match, &state);
|
---|
202 |
|
---|
203 | tdb_close(tdb2);
|
---|
204 |
|
---|
205 | return state.matched_packet;
|
---|
206 | }
|
---|