r5408: - added testing for the behaviour of the special 0x1c name
[Samba/gebeck_regimport.git] / source4 / nbt_server / winswack.c
blob190b1cdec7ddca4f7a9e0bd1dd281c2ef86d09ae
1 /*
2 Unix SMB/CIFS implementation.
4 "secure" wins server WACK processing
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "nbt_server/nbt_server.h"
25 #include "nbt_server/winsdb.h"
26 #include "system/time.h"
28 struct wack_state {
29 struct wins_server *winssrv;
30 struct nbt_name_socket *nbtsock;
31 struct nbt_name_packet *request_packet;
32 struct winsdb_record *rec;
33 const char *src_address;
34 int src_port;
35 const char **owner_addresses;
36 const char *reg_address;
37 struct nbt_name_query query;
42 deny a registration request
44 static void wins_wack_deny(struct wack_state *state)
46 nbtd_name_registration_reply(state->nbtsock, state->request_packet,
47 state->src_address, state->src_port, NBT_RCODE_ACT);
48 DEBUG(4,("WINS: denied name registration request for %s from %s\n",
49 nbt_name_string(state, state->rec->name), state->src_address));
50 talloc_free(state);
54 allow a registration request
56 static void wins_wack_allow(struct wack_state *state)
58 uint32_t ttl;
59 time_t now = time(NULL);
60 struct winsdb_record *rec = state->rec;
62 nbtd_name_registration_reply(state->nbtsock, state->request_packet,
63 state->src_address, state->src_port, NBT_RCODE_OK);
65 rec->addresses = str_list_add(rec->addresses, state->reg_address);
66 if (rec->addresses == NULL) goto failed;
68 ttl = wins_server_ttl(state->winssrv, state->request_packet->additional[0].ttl);
69 if (now + ttl > rec->expire_time) {
70 rec->expire_time = now + ttl;
72 rec->registered_by = state->src_address;
74 winsdb_modify(state->winssrv, rec);
76 DEBUG(4,("WINS: accepted registration of %s with address %s\n",
77 nbt_name_string(state, rec->name), state->reg_address));
79 failed:
80 talloc_free(state);
84 called when a name query to a current owner completes
86 static void wins_wack_handler(struct nbt_name_request *req)
88 struct wack_state *state = talloc_get_type(req->async.private, struct wack_state);
89 NTSTATUS status;
90 int i;
91 struct winsdb_record *rec = state->rec;
93 status = nbt_name_query_recv(req, state, &state->query);
95 /* if we timed out then try the next owner address, if any */
96 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
97 state->owner_addresses++;
98 if (state->owner_addresses[0] == NULL) {
99 wins_wack_allow(state);
100 return;
102 state->query.in.dest_addr = state->owner_addresses[0];
104 req = nbt_name_query_send(state->nbtsock, &state->query);
105 if (req == NULL) goto failed;
107 req->async.fn = wins_wack_handler;
108 req->async.private = state;
109 return;
112 /* if the owner denies it holds the name, then allow
113 the registration */
114 if (!NT_STATUS_IS_OK(status)) {
115 wins_wack_allow(state);
116 return;
119 /* if the owner still wants the name and doesn't reply
120 with the address trying to be registered, then deny
121 the registration */
122 if (!str_list_check(state->query.out.reply_addrs, state->reg_address)) {
123 wins_wack_deny(state);
124 return;
127 /* we are going to allow the registration, but first remove any addresses
128 from the record that aren't in the reply from the client */
129 for (i=0;rec->addresses[i];) {
130 if (!str_list_check(state->query.out.reply_addrs, rec->addresses[i])) {
131 str_list_remove(rec->addresses, rec->addresses[i]);
132 } else {
133 i++;
137 wins_wack_allow(state);
138 return;
140 failed:
141 talloc_free(state);
146 a client has asked to register a unique name that someone else owns. We
147 need to ask each of the current owners if they still want it. If they do
148 then reject the registration, otherwise allow it
150 void wins_register_wack(struct nbt_name_socket *nbtsock,
151 struct nbt_name_packet *packet,
152 struct winsdb_record *rec,
153 const char *src_address, int src_port)
155 struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private,
156 struct nbtd_interface);
157 struct wins_server *winssrv = iface->nbtsrv->winssrv;
158 struct wack_state *state;
159 struct nbt_name_request *req;
160 uint32_t ttl;
162 state = talloc(nbtsock, struct wack_state);
163 if (state == NULL) goto failed;
165 /* package up the state variables for this wack request */
166 state->winssrv = winssrv;
167 state->nbtsock = nbtsock;
168 state->request_packet = talloc_steal(state, packet);
169 state->rec = talloc_steal(state, rec);
170 state->src_port = src_port;
171 state->owner_addresses = rec->addresses;
172 state->reg_address = packet->additional[0].rdata.netbios.addresses[0].ipaddr;
173 state->src_address = talloc_strdup(state, src_address);
174 if (state->src_address == NULL) goto failed;
176 /* setup a name query to the first address */
177 state->query.in.name = *rec->name;
178 state->query.in.dest_addr = state->owner_addresses[0];
179 state->query.in.broadcast = False;
180 state->query.in.wins_lookup = True;
181 state->query.in.timeout = 1;
182 state->query.in.retries = 2;
184 /* the LOGON type is a nasty hack */
185 if (rec->name->type == NBT_NAME_LOGON) {
186 wins_wack_allow(state);
187 return;
190 /* send a WACK to the client, specifying the maximum time it could
191 take to check with the owner, plus some slack */
192 ttl = 5 + 4 * str_list_length(rec->addresses);
193 nbtd_wack_reply(nbtsock, packet, src_address, src_port, ttl);
195 req = nbt_name_query_send(nbtsock, &state->query);
196 if (req == NULL) goto failed;
198 req->async.fn = wins_wack_handler;
199 req->async.private = state;
200 return;
202 failed:
203 talloc_free(state);
204 nbtd_name_registration_reply(nbtsock, packet, src_address, src_port, NBT_RCODE_SVR);