1 | /* |
---|
2 | ************************************************************************** |
---|
3 | * |
---|
4 | * Component: RDBG |
---|
5 | * Module: servcon.c |
---|
6 | * |
---|
7 | * Synopsis: Management of RPC client connections. |
---|
8 | * |
---|
9 | * $Id$ |
---|
10 | * |
---|
11 | ************************************************************************** |
---|
12 | */ |
---|
13 | |
---|
14 | #include <sys/errno.h> |
---|
15 | #include <rdbg/rdbg.h> |
---|
16 | #include <rdbg/servrpc.h> |
---|
17 | |
---|
18 | /* |
---|
19 | * ConnCreate - create a new connection entry for a client. |
---|
20 | * |
---|
21 | * This function finds an empty entry in the connection array |
---|
22 | * or makes space. It fills in the fields that are passed to it. |
---|
23 | * It does not do any validation on net addresses nor does it |
---|
24 | * start a validation cycle on other clients. This is done by |
---|
25 | * the caller. |
---|
26 | */ |
---|
27 | |
---|
28 | int |
---|
29 | ConnCreate (struct svc_req* rqstp, open_in* in) |
---|
30 | { |
---|
31 | NET_OPAQUE sender; |
---|
32 | int idx; |
---|
33 | CONN_LIST* clst; |
---|
34 | |
---|
35 | setErrno (0); |
---|
36 | |
---|
37 | /* Convert to valid Net address */ |
---|
38 | if (! TspTranslateRpcAddr (rqstp, &sender)) { |
---|
39 | DPRINTF (("ConnCreate: TspTranslateRpcAddr failed\n")); |
---|
40 | return -1; |
---|
41 | } |
---|
42 | if (! TspValidateAddr ((NET_OPAQUE*) in->back_port, &sender)) { |
---|
43 | DPRINTF (("ConnCreate: TspValidateAddr failed\n")); |
---|
44 | return -1; /* errno now setup with error */ |
---|
45 | } |
---|
46 | |
---|
47 | /* look for an empty connection entry */ |
---|
48 | for (idx = 0; idx < conn_list_cnt; idx++) { |
---|
49 | if (!conn_list[idx].in_use) |
---|
50 | break; /* an empty one found */ |
---|
51 | } |
---|
52 | |
---|
53 | if (idx >= conn_list_cnt) { /* no empties, create space */ |
---|
54 | CONN_LIST* tmp_conn_list = conn_list; |
---|
55 | |
---|
56 | conn_list_cnt += CONN_LIST_INC; |
---|
57 | if (conn_list) { |
---|
58 | conn_list = (CONN_LIST *) Realloc (conn_list, /* extend */ |
---|
59 | conn_list_cnt * sizeof (CONN_LIST)); |
---|
60 | } else { |
---|
61 | conn_list = (CONN_LIST *)Malloc(conn_list_cnt * sizeof(CONN_LIST)); |
---|
62 | } |
---|
63 | |
---|
64 | if (!conn_list) { /* unable to get space */ |
---|
65 | if ((conn_list_cnt -= CONN_LIST_INC)) { |
---|
66 | /* was realloc, restore space */ |
---|
67 | conn_list = tmp_conn_list; |
---|
68 | } |
---|
69 | return -1; /* errno set by failed alloc */ |
---|
70 | } |
---|
71 | /* clear newly created memory */ |
---|
72 | memset (conn_list + idx, 0, CONN_LIST_INC * sizeof (CONN_LIST)); |
---|
73 | } else { /* clear new entry */ |
---|
74 | memset (conn_list + idx, 0, sizeof (CONN_LIST)); |
---|
75 | } |
---|
76 | clst = conn_list + idx; |
---|
77 | |
---|
78 | clst->in_use = True; /* now in use */ |
---|
79 | clst->sender = sender; |
---|
80 | memcpy (&clst->back_port, &in->back_port, sizeof (NET_OPAQUE)); |
---|
81 | memcpy (&clst->route, &in->destination, sizeof (NET_OPAQUE)); |
---|
82 | clst->debug_type = (UCHAR) in->debug_type; |
---|
83 | clst->flags = in->flags; |
---|
84 | strncpy (clst->user_name, in->user_name, NAMEMAX-1); |
---|
85 | clst->user_name [NAMEMAX-1] = 0; |
---|
86 | |
---|
87 | return idx; |
---|
88 | } |
---|
89 | |
---|
90 | /* |
---|
91 | * ConnDelete - remove connection entry when shutdown. |
---|
92 | * |
---|
93 | */ |
---|
94 | |
---|
95 | void |
---|
96 | ConnDelete (int conn, struct svc_req* rqstp, close_control control) |
---|
97 | { |
---|
98 | CONN_LIST* clst = conn_list + conn; |
---|
99 | int idx; |
---|
100 | Boolean prim; |
---|
101 | |
---|
102 | if (! clst->in_use) return; /* not active */ |
---|
103 | |
---|
104 | for (idx = 0; idx < pid_list_cnt; idx++) { |
---|
105 | PID_LIST* plst = pid_list + idx; |
---|
106 | |
---|
107 | if (! PIDMAP_TEST (conn, idx)) continue; |
---|
108 | |
---|
109 | /* found a controlled pid */ |
---|
110 | prim = (plst->primary_conn == conn) ? True : False; |
---|
111 | TgtDetachCon (conn, idx, True); |
---|
112 | |
---|
113 | /* if still running or alive, we use close control on it */ |
---|
114 | if (! plst->pid) |
---|
115 | continue; /* entry gone */ |
---|
116 | |
---|
117 | if (prim && control == CLOSE_KILL) { |
---|
118 | /* kill off process */ |
---|
119 | TgtKillAndDelete (plst, rqstp, True); |
---|
120 | } else if (! plst->owners) { |
---|
121 | /* no owners left */ |
---|
122 | if (control == CLOSE_DETACH) { |
---|
123 | TgtKillAndDelete (plst, rqstp, False); |
---|
124 | } |
---|
125 | if (control == CLOSE_DETACH || PROC_TERMINATED (plst)) { |
---|
126 | TgtDelete (plst, conn, (control==CLOSE_DETACH) ? |
---|
127 | BMSG_DETACH : 0); |
---|
128 | } |
---|
129 | } |
---|
130 | } |
---|
131 | if (clst->list) { |
---|
132 | Free (clst->list); /* free allocated memory */ |
---|
133 | } |
---|
134 | DPRINTF (("ConnDelete: Connection closed for port %u\n", |
---|
135 | HL_W(*((UINT16*) &clst->back_port.c[2])))); |
---|
136 | |
---|
137 | clst->in_use = False; /* free it back */ |
---|
138 | } |
---|