r5352: added a function nbt_name_string() that formats a nbt_name structure
[jelmer/samba4-debian.git] / source / nbt_server / packet.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    packet utility functions
5
6    Copyright (C) Andrew Tridgell        2005
7    
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
24 #include "dlinklist.h"
25 #include "nbt_server/nbt_server.h"
26
27 /*
28   we received a badly formed packet - log it
29 */
30 void nbtd_bad_packet(struct nbt_name_packet *packet, 
31                      const char *src_address, const char *reason)
32 {
33         DEBUG(2,("nbtd: bad packet '%s' from %s\n", reason, src_address));
34         if (DEBUGLVL(5)) {
35                 NDR_PRINT_DEBUG(nbt_name_packet, packet);               
36         }
37 }
38
39
40 /*
41   see if an incoming packet is a broadcast packet from one of our own
42   interfaces
43 */
44 BOOL nbtd_self_packet(struct nbt_name_socket *nbtsock, 
45                       struct nbt_name_packet *packet, 
46                       const char *src_address, int src_port)
47 {
48         struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
49                                                        struct nbtd_interface);
50         struct nbtd_server *nbtsrv = iface->nbtsrv;
51         
52         /* if its not a broadcast then its not considered a self packet */
53         if (!(packet->operation & NBT_FLAG_BROADCAST)) {
54                 return False;
55         }
56
57         /* if its not from the nbt port, then it wasn't a broadcast from us */
58         if (src_port != lp_nbt_port()) {
59                 return False;
60         }
61
62         /* this uses the fact that iface->nbtsock is our non-broadcast
63            listen address */
64         if (iface->nbtsock == nbtsock &&
65             iface != iface->nbtsrv->bcast_interface) {
66                 return False;
67         }
68
69         /* we have to loop over our interface list, seeing if its from
70            one of our own interfaces */
71         for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
72                 if (strcmp(src_address, iface->ip_address) == 0) {
73                         return True;
74                 }
75         }
76
77         return False;
78 }
79
80
81 /*
82   send a name query reply
83 */
84 void nbtd_name_query_reply(struct nbt_name_socket *nbtsock, 
85                            struct nbt_name_packet *request_packet, 
86                            const char *src_address, int src_port,
87                            struct nbt_name *name, uint32_t ttl,
88                            uint16_t nb_flags, const char **addresses)
89 {
90         struct nbt_name_packet *packet;
91         size_t num_addresses = str_list_length(addresses);
92         int i;
93
94         if (num_addresses == 0) {
95                 DEBUG(3,("No addresses in name query reply - failing\n"));
96                 return;
97         }
98
99         packet = talloc_zero(nbtsock, struct nbt_name_packet);
100         if (packet == NULL) return;
101
102         packet->name_trn_id = request_packet->name_trn_id;
103         packet->ancount = 1;
104         packet->operation = 
105                 NBT_FLAG_REPLY | 
106                 NBT_OPCODE_QUERY | 
107                 NBT_FLAG_AUTHORITIVE |
108                 NBT_FLAG_RECURSION_DESIRED |
109                 NBT_FLAG_RECURSION_AVAIL;
110
111         packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
112         if (packet->answers == NULL) goto failed;
113
114         packet->answers[0].name     = *name;
115         packet->answers[0].rr_type  = NBT_QTYPE_NETBIOS;
116         packet->answers[0].rr_class = NBT_QCLASS_IP;
117         packet->answers[0].ttl      = ttl;
118         packet->answers[0].rdata.netbios.length = num_addresses*6;
119         packet->answers[0].rdata.netbios.addresses = 
120                 talloc_array(packet->answers, struct nbt_rdata_address, num_addresses);
121         if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
122
123         for (i=0;i<num_addresses;i++) {
124                 struct nbt_rdata_address *addr = 
125                         &packet->answers[0].rdata.netbios.addresses[i];
126                 addr->nb_flags = nb_flags;
127                 addr->ipaddr = talloc_strdup(packet->answers, addresses[i]);
128                 if (addr->ipaddr == NULL) goto failed;
129         }
130
131         DEBUG(7,("Sending name query reply for %s at %s to %s:%d\n", 
132                  nbt_name_string(packet, name), addresses[0], src_address, src_port));
133         
134         nbt_name_reply_send(nbtsock, src_address, src_port, packet);
135
136 failed:
137         talloc_free(packet);
138 }
139
140
141 /*
142   send a negative name query reply
143 */
144 void nbtd_negative_name_query_reply(struct nbt_name_socket *nbtsock, 
145                                     struct nbt_name_packet *request_packet, 
146                                     const char *src_address, int src_port)
147 {
148         struct nbt_name_packet *packet;
149         struct nbt_name *name = &request_packet->questions[0].name;
150
151         packet = talloc_zero(nbtsock, struct nbt_name_packet);
152         if (packet == NULL) return;
153
154         packet->name_trn_id = request_packet->name_trn_id;
155         packet->ancount = 1;
156         packet->operation = 
157                 NBT_FLAG_REPLY | 
158                 NBT_OPCODE_QUERY | 
159                 NBT_FLAG_AUTHORITIVE |
160                 NBT_RCODE_NAM;
161
162         packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
163         if (packet->answers == NULL) goto failed;
164
165         packet->answers[0].name      = *name;
166         packet->answers[0].rr_type   = NBT_QTYPE_NULL;
167         packet->answers[0].rr_class  = NBT_QCLASS_IP;
168         packet->answers[0].ttl       = 0;
169         ZERO_STRUCT(packet->answers[0].rdata);
170
171         DEBUG(7,("Sending negative name query reply for %s to %s:%d\n", 
172                  nbt_name_string(packet, name), src_address, src_port));
173         
174         nbt_name_reply_send(nbtsock, src_address, src_port, packet);
175
176 failed:
177         talloc_free(packet);
178 }
179
180 /*
181   send a name defense reply
182 */
183 void nbtd_negative_name_registration_reply(struct nbt_name_socket *nbtsock, 
184                                            struct nbt_name_packet *request_packet, 
185                                            const char *src_address, int src_port)
186 {
187         struct nbt_name_packet *packet;
188         struct nbt_name *name = &request_packet->questions[0].name;
189
190         packet = talloc_zero(nbtsock, struct nbt_name_packet);
191         if (packet == NULL) return;
192
193         packet->name_trn_id = request_packet->name_trn_id;
194         packet->ancount = 1;
195         packet->operation = 
196                 NBT_FLAG_REPLY | 
197                 NBT_OPCODE_REGISTER |
198                 NBT_FLAG_AUTHORITIVE |
199                 NBT_FLAG_RECURSION_DESIRED |
200                 NBT_FLAG_RECURSION_AVAIL |
201                 NBT_RCODE_ACT;
202         
203         packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
204         if (packet->answers == NULL) goto failed;
205
206         packet->answers[0].name     = *name;
207         packet->answers[0].rr_type  = NBT_QTYPE_NETBIOS;
208         packet->answers[0].rr_class = NBT_QCLASS_IP;
209         packet->answers[0].ttl      = 0;
210         packet->answers[0].rdata    = request_packet->additional[0].rdata;
211
212         DEBUG(7,("Sending negative name registration reply for %s to %s:%d\n", 
213                  nbt_name_string(packet, name), src_address, src_port));
214         
215         nbt_name_reply_send(nbtsock, src_address, src_port, packet);
216
217 failed:
218         talloc_free(packet);
219 }