r10706: split out the irpc server functions in the NBT server, so the mainline
[garming/samba-autobuild/.git] / source4 / nbt_server / irpc.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    irpc services for the NBT server
5
6    Copyright (C) Andrew Tridgell        2005
7    Copyright (C) Volker Lendecke        2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "smbd/service_task.h"
26 #include "nbt_server/nbt_server.h"
27
28
29 /*
30   serve out the nbt statistics
31 */
32 static NTSTATUS nbtd_information(struct irpc_message *msg, 
33                                  struct nbtd_information *r)
34 {
35         struct nbtd_server *server = talloc_get_type(msg->private, struct nbtd_server);
36
37         switch (r->in.level) {
38         case NBTD_INFO_STATISTICS:
39                 r->out.info.stats = &server->stats;
40                 break;
41         }
42
43         return NT_STATUS_OK;
44 }
45
46
47 /*
48   winbind needs to be able to do a getdc request, but some windows
49   servers always send the reply to port 138, regardless of the request
50   port. To cope with this we use a irpc request to the NBT server
51   which has port 138 open, and thus can receive the replies
52 */
53 struct getdc_state {
54         struct irpc_message *msg;
55         struct nbtd_getdcname *req;
56 };
57
58 static void getdc_recv_ntlogon_reply(struct dgram_mailslot_handler *dgmslot, 
59                                      struct nbt_dgram_packet *packet, 
60                                      const char *src_address, int src_port)
61 {
62         struct getdc_state *s =
63                 talloc_get_type(dgmslot->private, struct getdc_state);
64
65         struct nbt_ntlogon_packet ntlogon;
66         NTSTATUS status;
67
68         status = dgram_mailslot_ntlogon_parse(dgmslot, packet, packet,
69                                               &ntlogon);
70         if (!NT_STATUS_IS_OK(status)) {
71                 DEBUG(5, ("dgram_mailslot_ntlogon_parse failed: %s\n",
72                           nt_errstr(status)));
73                 goto done;
74         }
75
76         status = NT_STATUS_NO_LOGON_SERVERS;
77
78         DEBUG(10, ("reply: command=%d\n", ntlogon.command));
79
80         switch (ntlogon.command) {
81         case NTLOGON_SAM_LOGON:
82                 DEBUG(0, ("Huh -- got NTLOGON_SAM_LOGON as reply\n"));
83                 break;
84         case NTLOGON_SAM_LOGON_REPLY: {
85                 const char *p = ntlogon.req.reply.server;
86
87                 DEBUG(10, ("NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, "
88                            "domain: %s\n", p, ntlogon.req.reply.user_name,
89                            ntlogon.req.reply.domain));
90
91                 if (*p == '\\') p += 1;
92                 if (*p == '\\') p += 1;
93
94                 s->req->out.dcname = talloc_strdup(s->req, p);
95                 if (s->req->out.dcname == NULL) {
96                         DEBUG(0, ("talloc failed\n"));
97                         status = NT_STATUS_NO_MEMORY;
98                         goto done;
99                 }
100                 status = NT_STATUS_OK;
101                 break;
102         }
103         default:
104                 DEBUG(0, ("Got unknown packet: %d\n", ntlogon.command));
105                 break;
106         }
107
108  done:
109         irpc_send_reply(s->msg, status);
110 }
111
112 static NTSTATUS nbtd_getdcname(struct irpc_message *msg, 
113                                struct nbtd_getdcname *req)
114 {
115         struct nbtd_server *server =
116                 talloc_get_type(msg->private, struct nbtd_server);
117
118         struct getdc_state *s;
119         struct nbt_ntlogon_packet p;
120         struct nbt_ntlogon_sam_logon *r;
121         struct nbt_dgram_socket *sock;
122         struct nbt_name src, dst;
123         struct dgram_mailslot_handler *handler;
124         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
125
126         DEBUG(0, ("nbtd_getdcname called\n"));
127
128         sock = server->interfaces[0].dgmsock;
129
130         s = talloc(msg, struct getdc_state);
131         NT_STATUS_HAVE_NO_MEMORY(s);
132
133         s->msg = msg;
134         s->req = req;
135         
136         handler = dgram_mailslot_temp(sock, NBT_MAILSLOT_GETDC,
137                                       getdc_recv_ntlogon_reply, s);
138         NT_STATUS_HAVE_NO_MEMORY(handler);
139         
140         ZERO_STRUCT(p);
141         p.command = NTLOGON_SAM_LOGON;
142         r = &p.req.logon;
143         r->request_count = 0;
144         r->computer_name = req->in.my_computername;
145         r->user_name = req->in.my_accountname;
146         r->mailslot_name = handler->mailslot_name;
147         r->acct_control = req->in.account_control;
148         r->sid = *req->in.domain_sid;
149         r->nt_version = 1;
150         r->lmnt_token = 0xffff;
151         r->lm20_token = 0xffff;
152
153         make_nbt_name_client(&src, req->in.my_computername);
154         make_nbt_name(&dst, req->in.domainname, 0x1c);
155
156         status = dgram_mailslot_ntlogon_send(sock, DGRAM_DIRECT_GROUP,
157                                              &dst, req->in.ip_address, 138,
158                                              &src, &p);
159         if (!NT_STATUS_IS_OK(status)) {
160                 DEBUG(0, ("dgram_mailslot_ntlogon_send failed: %s\n",
161                           nt_errstr(status)));
162                 return status;
163         }
164
165         msg->defer_reply = True;
166         return NT_STATUS_OK;
167 }
168
169
170 /*
171   register the irpc handlers for the nbt server
172 */
173 void nbtd_register_irpc(struct nbtd_server *nbtsrv)
174 {
175         NTSTATUS status;
176         struct task_server *task = nbtsrv->task;
177
178         status = IRPC_REGISTER(task->msg_ctx, irpc, NBTD_INFORMATION, 
179                                nbtd_information, nbtsrv);
180         if (!NT_STATUS_IS_OK(status)) {
181                 task_server_terminate(task, "nbtd failed to setup monitoring");
182                 return;
183         }
184
185         status = IRPC_REGISTER(task->msg_ctx, irpc, NBTD_GETDCNAME,
186                                nbtd_getdcname, nbtsrv);
187         if (!NT_STATUS_IS_OK(status)) {
188                 task_server_terminate(task, "nbtd failed to setup getdcname "
189                                       "handler");
190                 return;
191         }
192 }