fdb46dbba50175de3d2874934bf98417ca707685
[metze/samba/wip.git] / source3 / utils / net_time.c
1 /*
2    Samba Unix/Linux SMB client library
3    net time command
4    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "utils/net.h"
21 #include "libsmb/nmblib.h"
22
23 /*
24   return the time on a server. This does not require any authentication
25 */
26 static time_t cli_servertime(const char *host, struct sockaddr_storage *pss, int *zone)
27 {
28         struct nmb_name calling, called;
29         time_t ret = 0;
30         struct cli_state *cli = NULL;
31         NTSTATUS status;
32
33         cli = cli_initialise();
34         if (!cli) {
35                 goto done;
36         }
37
38         status = cli_connect(cli, host, pss);
39         if (!NT_STATUS_IS_OK(status)) {
40                 fprintf(stderr, _("Can't contact server %s. Error %s\n"),
41                         host, nt_errstr(status));
42                 goto done;
43         }
44
45         make_nmb_name(&calling, global_myname(), 0x0);
46         if (host) {
47                 make_nmb_name(&called, host, 0x20);
48         } else {
49                 make_nmb_name(&called, "*SMBSERVER", 0x20);
50         }
51
52         if (!cli_session_request(cli, &calling, &called)) {
53                 fprintf(stderr, _("Session request failed\n"));
54                 goto done;
55         }
56         status = cli_negprot(cli);
57         if (!NT_STATUS_IS_OK(status)) {
58                 fprintf(stderr, _("Protocol negotiation failed: %s\n"),
59                         nt_errstr(status));
60                 goto done;
61         }
62
63         ret = cli->servertime;
64         if (zone) *zone = cli->serverzone;
65
66 done:
67         if (cli) {
68                 cli_shutdown(cli);
69         }
70         return ret;
71 }
72
73 /* find the servers time on the opt_host host */
74 static time_t nettime(struct net_context *c, int *zone)
75 {
76         return cli_servertime(c->opt_host,
77                               c->opt_have_ip? &c->opt_dest_ip : NULL, zone);
78 }
79
80 /* return a time as a string ready to be passed to /bin/date */
81 static const char *systime(time_t t)
82 {
83         struct tm *tm;
84
85         tm = localtime(&t);
86         if (!tm) {
87                 return "unknown";
88         }
89
90         return talloc_asprintf(talloc_tos(), "%02d%02d%02d%02d%04d.%02d",
91                                tm->tm_mon+1, tm->tm_mday, tm->tm_hour,
92                                tm->tm_min, tm->tm_year + 1900, tm->tm_sec);
93 }
94
95 int net_time_usage(struct net_context *c, int argc, const char **argv)
96 {
97         d_printf(_(
98 "net time\n\tdisplays time on a server\n\n"
99 "net time system\n\tdisplays time on a server in a format ready for /bin/date\n\n"
100 "net time set\n\truns /bin/date with the time from the server\n\n"
101 "net time zone\n\tdisplays the timezone in hours from GMT on the remote computer\n\n"
102 "\n"));
103         net_common_flags_usage(c, argc, argv);
104         return -1;
105 }
106
107 /* try to set the system clock */
108 static int net_time_set(struct net_context *c, int argc, const char **argv)
109 {
110         struct timeval tv;
111         int result;
112
113         tv.tv_sec = nettime(c, NULL);
114         tv.tv_usec=0;
115
116         if (tv.tv_sec == 0) return -1;
117
118         result = settimeofday(&tv,NULL);
119
120         if (result)
121                 d_fprintf(stderr, _("setting system clock failed.  Error was (%s)\n"),
122                         strerror(errno));
123
124         return result;
125 }
126
127 /* display the time on a remote box in a format ready for /bin/date */
128 static int net_time_system(struct net_context *c, int argc, const char **argv)
129 {
130         time_t t;
131
132         if (c->display_usage) {
133                 d_printf(  "%s\n"
134                            "net time system\n"
135                            "    %s\n",
136                          _("Usage:"),
137                          _("Output remote time server time in a format "
138                            "ready for /bin/date"));
139                 return 0;
140         }
141
142         t = nettime(c, NULL);
143         if (t == 0) return -1;
144
145         printf("%s\n", systime(t));
146
147         return 0;
148 }
149
150 /* display the remote time server's offset to UTC */
151 static int net_time_zone(struct net_context *c, int argc, const char **argv)
152 {
153         int zone = 0;
154         int hours, mins;
155         char zsign;
156         time_t t;
157
158         if (c->display_usage) {
159                 d_printf(  "%s\n"
160                            "net time zone\n"
161                            "   %s\n",
162                          _("Usage:"),
163                          _("Display the remote time server's offset to "
164                            "UTC"));
165                 return 0;
166         }
167
168         t = nettime(c, &zone);
169
170         if (t == 0) return -1;
171
172         zsign = (zone > 0) ? '-' : '+';
173         if (zone < 0) zone = -zone;
174
175         zone /= 60;
176         hours = zone / 60;
177         mins = zone % 60;
178
179         printf("%c%02d%02d\n", zsign, hours, mins);
180
181         return 0;
182 }
183
184 /* display or set the time on a host */
185 int net_time(struct net_context *c, int argc, const char **argv)
186 {
187         time_t t;
188         struct functable func[] = {
189                 {
190                         "system",
191                         net_time_system,
192                         NET_TRANSPORT_LOCAL,
193                         N_("Display time ready for /bin/date"),
194                         N_("net time system\n"
195                            "    Display time ready for /bin/date")
196                 },
197                 {
198                         "set",
199                         net_time_set,
200                         NET_TRANSPORT_LOCAL,
201                         N_("Set the system time from time server"),
202                         N_("net time set\n"
203                            "    Set the system time from time server")
204                 },
205                 {
206                         "zone",
207                         net_time_zone,
208                         NET_TRANSPORT_LOCAL,
209                         N_("Display timezone offset from UTC"),
210                         N_("net time zone\n"
211                            "    Display timezone offset from UTC")
212                 },
213                 {NULL, NULL, 0, NULL, NULL}
214         };
215
216         if (argc != 0) {
217                 return net_run_function(c, argc, argv, "net time", func);
218         }
219
220         if (c->display_usage) {
221                 d_printf(  "%s\n"
222                            "net time\n"
223                            "    %s\n",
224                          _("Usage:"),
225                          _("Display the remote time server's time"));
226                 net_display_usage_from_functable(func);
227                 return 0;
228         }
229
230         if (!c->opt_host && !c->opt_have_ip &&
231             !find_master_ip(c->opt_target_workgroup, &c->opt_dest_ip)) {
232                 d_fprintf(stderr, _("Could not locate a time server.  Try "
233                                     "specifying a target host.\n"));
234                 net_time_usage(c, argc,argv);
235                 return -1;
236         }
237
238         /* default - print the time */
239         t = cli_servertime(c->opt_host, c->opt_have_ip? &c->opt_dest_ip : NULL,
240                            NULL);
241         if (t == 0) return -1;
242
243         d_printf("%s", ctime(&t));
244         return 0;
245 }