r5114: the nbtd task can now act as a basic B-node server. It registers its
[samba.git] / source / nbt_server / register.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    register our names
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   start a timer to refresh this name
29 */
30 static void nbt_start_refresh_timer(struct nbt_iface_name *iname)
31 {
32 }
33
34
35 /*
36   a name registration has completed
37 */
38 static void nbt_register_handler(struct nbt_name_request *req)
39 {
40         struct nbt_iface_name *iname = talloc_get_type(req->async.private, struct nbt_iface_name);
41         NTSTATUS status;
42         struct nbt_name_register io;
43
44         status = nbt_name_register_recv(req, iname, &io);
45         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
46                 /* good - nobody complained about our registration */
47                 iname->nb_flags |= NBT_NM_ACTIVE;
48                 DEBUG(3,("Registered %s<%02x> on interface %s\n",
49                          iname->name.name, iname->name.type, iname->iface->bcast_address));
50                 nbt_start_refresh_timer(iname);
51                 return;
52         }
53
54         if (!NT_STATUS_IS_OK(status)) {
55                 DEBUG(1,("Error registering %s<%02x> on interface %s - %s\n",
56                          iname->name.name, iname->name.type, iname->iface->bcast_address,
57                          nt_errstr(status)));
58                 return;
59         }
60
61         /* someone must have replied with an objection! */
62         iname->nb_flags |= NBT_NM_CONFLICT;
63         
64         DEBUG(1,("Name conflict registering %s<%02x> on interface %s - rcode %d from %s for %s\n",
65                  iname->name.name, iname->name.type, iname->iface->bcast_address,
66                  io.out.rcode, io.out.reply_from, io.out.reply_addr));
67 }
68
69
70 /*
71   register a name on a network interface
72 */
73 static void nbt_register_name_iface(struct nbt_interface *iface,
74                                     const char *name, enum nbt_name_type type,
75                                     uint16_t nb_flags)
76 {
77         struct nbt_iface_name *iname;
78         const char *scope = lp_netbios_scope();
79         struct nbt_name_register io;
80         struct nbt_name_request *req;
81
82         iname = talloc(iface, struct nbt_iface_name);
83         if (!iname) return;
84
85         iname->iface     = iface;
86         iname->name.name = talloc_strdup(iname, name);
87         iname->name.type = type;
88         if (scope && *scope) {
89                 iname->name.scope = talloc_strdup(iname, scope);
90         } else {
91                 iname->name.scope = NULL;
92         }
93         iname->nb_flags          = nb_flags;
94         iname->ttl               = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
95         iname->registration_time = timeval_zero();
96
97         DLIST_ADD(iface->names, iname);
98
99         if (nb_flags & NBT_NM_PERMANENT) {
100                 /* permanent names are not announced and are immediately active */
101                 iname->nb_flags |= NBT_NM_ACTIVE;
102                 iname->ttl       = 0;
103                 return;
104         }
105
106         /* setup a broadcast name registration request */
107         io.in.name            = iname->name;
108         io.in.dest_addr       = iface->bcast_address;
109         io.in.address         = iface->ip_address;
110         io.in.nb_flags        = nb_flags;
111         io.in.register_demand = False;
112         io.in.broadcast       = True;
113         io.in.ttl             = iname->ttl;
114         io.in.timeout         = 1;
115
116         req = nbt_name_register_send(iface->nbtsock, &io);
117         if (req == NULL) return;
118
119         req->async.fn = nbt_register_handler;
120         req->async.private = iname;
121 }
122
123
124 /*
125   register one name on all our interfaces
126 */
127 static void nbt_register_name(struct nbt_server *nbtsrv, 
128                               const char *name, enum nbt_name_type type,
129                               uint16_t nb_flags)
130 {
131         struct nbt_interface *iface;
132         
133         /* register with all the local interfaces */
134         for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
135                 nbt_register_name_iface(iface, name, type, nb_flags);
136         }
137
138         /* register on our general broadcast interface as a permanent name */
139         nbt_register_name_iface(nbtsrv->bcast_interface, name, type, nb_flags | NBT_NM_PERMANENT);
140
141         /* TODO: register with our WINS servers */
142 }
143
144
145 /*
146   register our names on all interfaces
147 */
148 void nbt_register_names(struct nbt_server *nbtsrv)
149 {
150         uint16_t nb_flags = NBT_NODE_M;
151
152         /* note that we don't initially mark the names "ACTIVE". They are 
153            marked active once registration is successful */
154         nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_CLIENT, nb_flags);
155         nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_USER,   nb_flags);
156         nbt_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_SERVER, nb_flags);
157         nbt_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_CLIENT, nb_flags | NBT_NM_GROUP);
158         nbt_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_SERVER, nb_flags | NBT_NM_GROUP);
159         nbt_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_CLIENT, nb_flags | NBT_NM_PERMANENT);
160         nbt_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_SERVER, nb_flags | NBT_NM_PERMANENT);
161 }