00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026
00027
00028
00029
00030 static void release_name_response(struct subnet_record *subrec,
00031 struct response_record *rrec, struct packet_struct *p)
00032 {
00033
00034
00035
00036
00037 struct nmb_packet *nmb = &p->packet.nmb;
00038 BOOL bcast = nmb->header.nm_flags.bcast;
00039 BOOL success = True;
00040 struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
00041 struct nmb_name *answer_name = &nmb->answers->rr_name;
00042 struct in_addr released_ip;
00043
00044
00045
00046 if (!nmb_name_equal(question_name, answer_name)) {
00047 DEBUG(0,("release_name_response: Answer name %s differs from question name %s.\n",
00048 nmb_namestr(answer_name), nmb_namestr(question_name)));
00049 return;
00050 }
00051
00052 if (bcast) {
00053
00054 return;
00055 }
00056
00057
00058 if (nmb->header.rcode != 0) {
00059
00060 success = False;
00061
00062 DEBUG(0,("release_name_response: WINS server at IP %s rejected our \
00063 name release of name %s with error code %d.\n",
00064 inet_ntoa(p->ip),
00065 nmb_namestr(answer_name), nmb->header.rcode));
00066 } else if (nmb->header.opcode == NMB_WACK_OPCODE) {
00067
00068
00069
00070 DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \
00071 name %s on subnet %s.\n",
00072 inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->subnet_name));
00073
00074 rrec->repeat_count = 0;
00075
00076 rrec->repeat_time = p->timestamp + nmb->answers->ttl;
00077 rrec->num_msgs--;
00078 return;
00079 }
00080
00081 DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n",
00082 success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name));
00083 if (success) {
00084 putip((char*)&released_ip ,&nmb->answers->rdata[2]);
00085
00086 if(rrec->success_fn)
00087 (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip);
00088 standard_success_release( subrec, rrec->userdata, answer_name, released_ip);
00089 } else {
00090
00091 if (rrec->fail_fn) {
00092 (*(release_name_fail_function)rrec->fail_fn)(subrec, rrec, answer_name);
00093 }
00094 }
00095
00096 remove_response_record(subrec, rrec);
00097 }
00098
00099
00100
00101
00102
00103 static void release_name_timeout_response(struct subnet_record *subrec,
00104 struct response_record *rrec)
00105 {
00106
00107
00108
00109
00110 struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
00111 BOOL bcast = sent_nmb->header.nm_flags.bcast;
00112 struct nmb_name *question_name = &sent_nmb->question.question_name;
00113 struct in_addr released_ip;
00114
00115
00116 putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]);
00117
00118 if (!bcast) {
00119
00120 wins_srv_died(rrec->packet->ip, released_ip);
00121 }
00122
00123 DEBUG(5,("release_name_timeout_response: success in releasing name %s on subnet %s.\n",
00124 nmb_namestr(question_name), subrec->subnet_name));
00125
00126 if (rrec->success_fn) {
00127 (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip);
00128 }
00129
00130 standard_success_release( subrec, rrec->userdata, question_name, released_ip);
00131 remove_response_record(subrec, rrec);
00132 }
00133
00134
00135
00136
00137
00138
00139 static void wins_release_name(struct name_record *namerec,
00140 release_name_success_function success_fn,
00141 release_name_fail_function fail_fn,
00142 struct userdata_struct *userdata)
00143 {
00144 int t, i;
00145 char **wins_tags;
00146
00147
00148 wins_tags = wins_srv_tags();
00149
00150 for (t=0;wins_tags && wins_tags[t]; t++) {
00151 for (i = 0; i < namerec->data.num_ips; i++) {
00152 struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.ip[i]);
00153
00154 BOOL last_one = ((i==namerec->data.num_ips - 1) && !wins_tags[t+1]);
00155 if (queue_release_name(unicast_subnet,
00156 release_name_response,
00157 release_name_timeout_response,
00158 last_one?success_fn : NULL,
00159 last_one? fail_fn : NULL,
00160 last_one? userdata : NULL,
00161 &namerec->name,
00162 namerec->data.nb_flags,
00163 namerec->data.ip[i],
00164 wins_ip) == NULL) {
00165 DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
00166 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
00167 }
00168 }
00169 }
00170
00171 wins_srv_tags_free(wins_tags);
00172 }
00173
00174
00175
00176
00177
00178
00179 void release_name(struct subnet_record *subrec, struct name_record *namerec,
00180 release_name_success_function success_fn,
00181 release_name_fail_function fail_fn,
00182 struct userdata_struct *userdata)
00183 {
00184 int i;
00185
00186
00187 if ((namerec->data.source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) {
00188 DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n",
00189 nmb_namestr(&namerec->name), subrec->subnet_name, namerec->data.source));
00190 return;
00191 }
00192
00193
00194 namerec->data.nb_flags |= NB_DEREG;
00195
00196
00197 if (subrec == unicast_subnet) {
00198 wins_release_name(namerec, success_fn, fail_fn, userdata);
00199 return;
00200 }
00201
00202
00203
00204
00205
00206
00207 for (i = 0; i < namerec->data.num_ips; i++) {
00208 if (queue_release_name(subrec,
00209 release_name_response,
00210 release_name_timeout_response,
00211 (i == (namerec->data.num_ips - 1)) ? success_fn : NULL,
00212 (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL,
00213 (i == (namerec->data.num_ips - 1)) ? userdata : NULL,
00214 &namerec->name,
00215 namerec->data.nb_flags,
00216 namerec->data.ip[i],
00217 subrec->bcast_ip) == NULL) {
00218 DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
00219 nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
00220 }
00221 }
00222 }