1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36 
37 
38 #include "ndmagents.h"
39 
40 
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42 
ndma_client_session(struct ndm_session * sess,struct ndm_job_param * job,int swap_connect)43 int ndma_client_session(struct ndm_session* sess,
44                         struct ndm_job_param* job,
45                         int swap_connect)
46 {
47   int rc;
48 
49   rc = ndma_job_audit(job, 0, 0);
50   if (rc) return -1;
51 
52   /*
53    * Old behaviour enable all agents.
54    */
55   sess->control_agent_enabled = 1;
56   sess->data_agent_enabled = 1;
57   sess->tape_agent_enabled = 1;
58   sess->robot_agent_enabled = 1;
59 
60   /*
61    * Old behaviour enable session snooping
62    */
63   sess->conn_snooping = 1;
64 
65   /*
66    * Old behaviour enable media info dumping.
67    */
68   sess->dump_media_info = 1;
69 
70   rc = ndma_session_initialize(sess);
71   if (rc) return rc;
72 
73   memcpy(&sess->control_acb->job, job, sizeof(struct ndm_job_param));
74 
75   sess->control_acb->job.index_log.nfc = sess->param->log.nfc;
76 
77   sess->control_acb->swap_connect = swap_connect;
78 
79   rc = ndma_session_commission(sess);
80   if (rc) return rc;
81 
82   rc = ndmca_connect_control_agent(sess);
83   if (rc) return rc; /* already tattled */
84 
85   sess->conn_open = 1;
86   sess->conn_authorized = 1;
87 
88   rc = ndmca_control_agent(sess);
89 
90   ndma_session_decommission(sess);
91   ndma_session_destroy(sess);
92 
93   return rc;
94 }
95 
96 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
97 
98 
99 #ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
100 
ndma_server_session(struct ndm_session * sess,int control_sock)101 int ndma_server_session(struct ndm_session* sess, int control_sock)
102 {
103   struct ndmconn* conn;
104   int rc;
105   struct sockaddr sa;
106   socklen_t len;
107 
108   /*
109    * Old behaviour enable all agents.
110    */
111   sess->control_agent_enabled = 1;
112   sess->data_agent_enabled = 1;
113   sess->tape_agent_enabled = 1;
114   sess->robot_agent_enabled = 1;
115 
116   /*
117    * Old behaviour enable session snooping
118    */
119   sess->conn_snooping = 1;
120 
121   /*
122    * Old behaviour enable media info dumping.
123    */
124   sess->dump_media_info = 1;
125 
126   rc = ndma_session_initialize(sess);
127   if (rc) return rc;
128 
129   rc = ndma_session_commission(sess);
130   if (rc) return rc;
131 
132   len = sizeof sa;
133   rc = getpeername(control_sock, &sa, &len);
134   if (rc < 0) {
135     perror("getpeername");
136   } else {
137     char ip_addr[100];
138     ndmalogf(sess, 0, 2, "Connection accepted from %s:%u",
139              inet_ntop(AF_INET, &(((struct sockaddr_in*)&sa)->sin_addr),
140                        ip_addr, sizeof(ip_addr)));
141   }
142 
143   len = sizeof sa;
144   rc = getsockname(control_sock, &sa, &len);
145   if (rc < 0) {
146     perror("getsockname");
147   } else {
148     char ip_addr[100];
149     ndmalogf(sess, 0, 2, "Connection accepted to %s",
150              inet_ntop(AF_INET, &((struct sockaddr_in*)&sa)->sin_addr, ip_addr,
151                        sizeof(ip_addr)));
152   }
153 
154   conn = ndmconn_initialize(0, "#C");
155   if (!conn) {
156     ndmalogf(sess, 0, 0, "can't init connection");
157     close(control_sock);
158     return -1;
159   }
160 
161   ndmos_condition_control_socket(sess, control_sock);
162 
163   if (sess->conn_snooping) {
164     ndmconn_set_snoop(conn, &sess->param->log, sess->param->log_level);
165   }
166   ndmconn_accept(conn, control_sock);
167 
168   conn->call = ndma_call;
169   conn->context = sess;
170 
171   sess->plumb.control = conn;
172 
173   while (!conn->chan.eof) { ndma_session_quantum(sess, 1000); }
174 
175 #if 1
176   {
177     char ip_addr[100];
178     ndmalogf(sess, 0, 2, "Connection close %s:%u",
179              inet_ntop(AF_INET, &(((struct sockaddr_in*)&sa)->sin_addr),
180                        ip_addr, sizeof(ip_addr)),
181              ntohs(((struct sockaddr_in*)&sa)->sin_port));
182   }
183 #endif
184 
185   ndmconn_destruct(conn);
186 
187   ndma_session_decommission(sess);
188   ndma_session_destroy(sess);
189 
190   return 0;
191 }
192 
ndma_daemon_session(struct ndm_session * sess,int port)193 int ndma_daemon_session(struct ndm_session* sess, int port)
194 {
195   int listen_sock;
196   int conn_sock, rc;
197   socklen_t len;
198   struct sockaddr sa;
199 
200   listen_sock = socket(AF_INET, SOCK_STREAM, 0);
201   if (listen_sock < 0) {
202     perror("socket");
203     return 1;
204   }
205 
206   ndmos_condition_listen_socket(sess, listen_sock);
207 
208   NDMOS_MACRO_SET_SOCKADDR(&sa, 0, port);
209 
210   if (bind(listen_sock, &sa, sizeof sa) < 0) {
211     perror("bind");
212     close(listen_sock);
213     return 2;
214   }
215 
216   if (listen(listen_sock, 1) < 0) {
217     perror("listen");
218     close(listen_sock);
219     return 3;
220   }
221 
222   for (;;) {
223     len = sizeof sa;
224     conn_sock = accept(listen_sock, &sa, &len);
225     if (conn_sock < 0) {
226       perror("accept");
227       close(listen_sock);
228       return 4;
229     }
230 
231     rc = fork();
232     if (rc < 0) {
233       perror("fork");
234       close(listen_sock);
235       close(conn_sock);
236       return 5;
237     }
238 
239     if (rc == 0) {
240       close(listen_sock);
241       ndma_server_session(sess, conn_sock);
242       exit(0);
243     }
244     close(conn_sock);
245   }
246 
247   return 0;
248 }
249 
250 #endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
251 
252 
ndma_session_distribute_quantum(struct ndm_session * sess)253 int ndma_session_distribute_quantum(struct ndm_session* sess)
254 {
255   int total_did_something = 0;
256   int did_something;
257 
258   do {
259     did_something = 0;
260 
261     if (sess->plumb.image_stream) did_something |= ndmis_quantum(sess);
262 
263 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
264     if (sess->tape_acb &&
265         sess->tape_acb->mover_state.state != NDMP9_MOVER_STATE_IDLE)
266       did_something |= ndmta_quantum(sess);
267 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
268 
269 #ifndef NDMOS_OPTION_NO_DATA_AGENT
270     if (sess->data_acb &&
271         sess->data_acb->data_state.state != NDMP9_DATA_STATE_IDLE)
272       did_something |= ndmda_quantum(sess);
273 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
274 
275     total_did_something |= did_something;
276 
277   } while (did_something);
278 
279   return total_did_something;
280 }
281 
282 
ndma_session_quantum(struct ndm_session * sess,int max_delay_secs)283 int ndma_session_quantum(struct ndm_session* sess, int max_delay_secs)
284 {
285   struct ndm_image_stream* is = sess->plumb.image_stream;
286   struct ndmconn* conn;
287   struct ndmconn* conntab[5];
288   int n_conntab;
289   struct ndmchan* chtab[16];
290   int n_chtab;
291   int i;
292   int max_delay_usec = max_delay_secs * 1000;
293 
294   /*
295    * Gather distinct connections
296    */
297   n_conntab = 0;
298   if ((conn = sess->plumb.control)) conntab[n_conntab++] = conn;
299   if ((conn = sess->plumb.data) && conn != sess->plumb.control)
300     conntab[n_conntab++] = conn;
301   if ((conn = sess->plumb.tape) && conn != sess->plumb.data &&
302       conn != sess->plumb.control)
303     conntab[n_conntab++] = conn;
304   if ((conn = sess->plumb.robot) && conn != sess->plumb.tape &&
305       conn != sess->plumb.data && conn != sess->plumb.control)
306     conntab[n_conntab++] = conn;
307 
308   /*
309    * Add connections to channel table
310    */
311   n_chtab = 0;
312   for (i = 0; i < n_conntab; i++) {
313     conn = conntab[i];
314     chtab[n_chtab++] = &conn->chan;
315   }
316 
317 #ifndef NDMOS_OPTION_NO_DATA_AGENT
318   /*
319    * Add DATA AGENT channels to table if active (!IDLE)
320    */
321   if (sess->data_acb &&
322       sess->data_acb->data_state.state != NDMP9_DATA_STATE_IDLE) {
323     chtab[n_chtab++] = &sess->data_acb->formatter_image;
324     chtab[n_chtab++] = &sess->data_acb->formatter_error;
325     chtab[n_chtab++] = &sess->data_acb->formatter_wrap;
326   }
327 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
328 
329   /*
330    * Add image stream to channel table
331    */
332   if (is && is->remote.connect_status == NDMIS_CONN_LISTEN) {
333     chtab[n_chtab++] = &is->remote.listen_chan;
334   }
335 
336   if (is) { chtab[n_chtab++] = &is->chan; }
337 
338   /*
339    * Let TAPE and DATA AGENTS get a bit of work done.
340    * This fills channel buffers as much as possible prior to blocking.
341    */
342   if (ndma_session_distribute_quantum(sess)) max_delay_usec = 0;
343 
344   /*
345    * Block awaiting ready I/O. Many channel buffers
346    * will have actual I/O (read/write) performed.
347    */
348   ndmchan_quantum(chtab, n_chtab, max_delay_usec);
349 
350   /*
351    * Tattle for debug
352    */
353   if (sess->param->log_level > 7) {
354     for (i = 0; i < n_chtab; i++) {
355       struct ndmchan* ch = chtab[i];
356       char buf[80];
357 
358       ndmchan_pp(ch, buf);
359       ndmalogf(sess, 0, 7, "ch %s", buf);
360     }
361   }
362 
363   /*
364    * Let TAPE and DATA AGENTS get a bit more work done.
365    * This will mostly digest whatever data just arrived.
366    */
367   ndma_session_distribute_quantum(sess);
368 
369   /*
370    * Dispatch any pending activity on the control connections
371    */
372   for (i = 0; i < n_conntab; i++) {
373     conn = conntab[i];
374     if (conn->chan.ready) {
375       conn->chan.ready = 0;
376       ndma_dispatch_conn(sess, conn);
377     }
378   }
379 
380   return 0;
381 }
382 
383 
ndma_session_initialize(struct ndm_session * sess)384 int ndma_session_initialize(struct ndm_session* sess)
385 {
386 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
387   if (sess->control_agent_enabled && ndmca_initialize(sess)) return -1;
388 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
389 
390 #ifndef NDMOS_OPTION_NO_DATA_AGENT
391   if (sess->data_agent_enabled && ndmda_initialize(sess)) return -1;
392 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
393 
394 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
395   if (sess->tape_agent_enabled && ndmta_initialize(sess)) return -1;
396 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
397 
398 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
399   if (sess->robot_agent_enabled && ndmra_initialize(sess)) return -1;
400 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
401 
402   return 0;
403 }
404 
ndma_session_commission(struct ndm_session * sess)405 int ndma_session_commission(struct ndm_session* sess)
406 {
407 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
408   if (sess->control_agent_enabled && ndmca_commission(sess)) return -1;
409 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
410 
411 #ifndef NDMOS_OPTION_NO_DATA_AGENT
412   if (sess->data_agent_enabled && ndmda_commission(sess)) return -1;
413 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
414 
415 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
416   if (sess->tape_agent_enabled && ndmta_commission(sess)) return -1;
417 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
418 
419 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
420   if (sess->robot_agent_enabled && ndmra_commission(sess)) return -1;
421 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
422 
423   return 0;
424 }
425 
ndma_session_decommission(struct ndm_session * sess)426 int ndma_session_decommission(struct ndm_session* sess)
427 {
428 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
429   if (sess->control_agent_enabled && ndmca_decommission(sess)) return -1;
430 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
431 
432 #ifndef NDMOS_OPTION_NO_DATA_AGENT
433   if (sess->data_agent_enabled && ndmda_decommission(sess)) return -1;
434 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
435 
436 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
437   if (sess->tape_agent_enabled && ndmta_decommission(sess)) return -1;
438 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
439 
440 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
441   if (sess->robot_agent_enabled && ndmra_decommission(sess)) return -1;
442 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
443 
444   return 0;
445 }
446 
ndma_session_destroy(struct ndm_session * sess)447 int ndma_session_destroy(struct ndm_session* sess)
448 {
449   if (sess->config_info) {
450     NDMOS_API_FREE(sess->config_info);
451     sess->config_info = NULL;
452   }
453 
454   ndmis_destroy(sess);
455 
456   if (sess->plumb.control) {
457     ndmconn_destruct(sess->plumb.control);
458     sess->plumb.control = NULL;
459   }
460   if (sess->plumb.data) {
461     ndmconn_destruct(sess->plumb.data);
462     sess->plumb.data = NULL;
463   }
464   if (sess->plumb.tape) {
465     ndmconn_destruct(sess->plumb.tape);
466     sess->plumb.tape = NULL;
467   }
468   if (sess->plumb.robot) {
469     ndmconn_destruct(sess->plumb.robot);
470     sess->plumb.robot = NULL;
471   }
472 
473 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
474   if (sess->control_agent_enabled && ndmca_destroy(sess)) return -1;
475 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
476 
477 #ifndef NDMOS_OPTION_NO_DATA_AGENT
478   if (sess->data_agent_enabled && ndmda_destroy(sess)) return -1;
479 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
480 
481 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
482   if (sess->tape_agent_enabled && ndmta_destroy(sess)) return -1;
483 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
484 
485 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
486   if (sess->robot_agent_enabled && ndmra_destroy(sess)) return -1;
487 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
488 
489   return 0;
490 }
491