]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/session.c
Various source format cleanups
[thirdparty/squid.git] / lib / rfcnb / session.c
1 #include "config.h"
2
3 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
4 *
5 * Version 1.0
6 * Session Routines ...
7 *
8 * Copyright (C) Richard Sharpe 1996
9 *
10 */
11
12 /*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28 int RFCNB_errno = 0;
29 int RFCNB_saved_errno = 0;
30 #define RFCNB_ERRNO
31
32 #include "rfcnb/std-includes.h"
33 #include <netinet/tcp.h>
34 #include "rfcnb/rfcnb.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-io.h"
37 #include "rfcnb/rfcnb-util.h"
38
39 #if HAVE_STRING_H
40 #include <string.h>
41 #endif
42
43 int RFCNB_Stats[RFCNB_MAX_STATS];
44
45 typedef void RFCNB_Prot_Print_Routine(FILE * fd, int dir, struct RFCNB_Pkt *pkt, int header, int payload);
46 RFCNB_Prot_Print_Routine *Prot_Print_Routine = NULL; /* Pointer to protocol print routine */
47
48 int RFCNB_Get_Last_Errno(void);
49 int RFCNB_Get_Error_Msg(int code, char *msg_buf, int len);
50 void RFCNB_Register_Print_Routine(RFCNB_Prot_Print_Routine * fn);
51
52 /* Set up a session with a remote name. We are passed Called_Name as a
53 * string which we convert to a NetBIOS name, ie space terminated, up to
54 * 16 characters only if we need to. If Called_Address is not empty, then
55 * we use it to connect to the remote end, but put in Called_Name ... Called
56 * Address can be a DNS based name, or a TCP/IP address ...
57 */
58
59 void *
60 RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, int port)
61 {
62 struct RFCNB_Con *con;
63 struct in_addr Dest_IP;
64 int Client;
65 BOOL redirect;
66 struct redirect_addr *redir_addr;
67 char *Service_Address;
68
69 /* Now, we really should look up the port in /etc/services ... */
70
71 if (port == 0)
72 port = RFCNB_Default_Port;
73
74 /* Create a connection structure first */
75
76 if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
77
78 RFCNB_errno = RFCNBE_NoSpace;
79 RFCNB_saved_errno = errno;
80 return (NULL);
81
82 }
83 con->fd = -0; /* no descriptor yet */
84 con->errn = 0; /* no error yet */
85 con->timeout = 0; /* no timeout */
86 con->redirects = 0;
87
88 /* Resolve that name into an IP address */
89
90 Service_Address = Called_Name;
91 if (strcmp(Called_Address, "") != 0) { /* If the Called Address = "" */
92 Service_Address = Called_Address;
93 }
94 if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
95
96 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
97 free(con);
98 return (NULL);
99
100 }
101 /* Now connect to the remote end */
102
103 redirect = TRUE; /* Fudge this one so we go once through */
104
105 while (redirect) { /* Connect and get session info etc */
106
107 redirect = FALSE; /* Assume all OK */
108
109 /* Build the redirect info. First one is first addr called */
110 /* And tack it onto the list of addresses we called */
111
112 if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
113
114 RFCNB_errno = RFCNBE_NoSpace;
115 RFCNB_saved_errno = errno;
116 free(con);
117 return (NULL);
118
119 }
120 memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
121 redir_addr->port = port;
122 redir_addr->next = NULL;
123
124 if (con->redirect_list == NULL) { /* Stick on head */
125
126 con->redirect_list = con->last_addr = redir_addr;
127
128 } else {
129
130 con->last_addr->next = redir_addr;
131 con->last_addr = redir_addr;
132
133 }
134
135 /* Now, make that connection */
136
137 if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
138
139 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
140 free(con);
141 return (NULL);
142
143 }
144 con->fd = Client;
145
146 /* Now send and handle the RFCNB session request */
147 /* If we get a redirect, we will comeback with redirect true
148 * and a new IP address in DEST_IP */
149
150 if ((errno = RFCNB_Session_Req(con,
151 Called_Name,
152 Calling_Name,
153 &redirect, &Dest_IP, &port)) < 0) {
154
155 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
156
157 RFCNB_Close(con->fd); /* Close it */
158 free(con);
159 return (NULL);
160
161 }
162 if (redirect) {
163
164 /* We have to close the connection, and then try again */
165
166 (con->redirects)++;
167
168 RFCNB_Close(con->fd); /* Close it */
169
170 }
171 }
172
173 return (con);
174 }
175
176 /* We send a packet to the other end ... for the moment, we treat the
177 * data as a series of pointers to blocks of data ... we should check the
178 * length ... */
179 int
180 RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
181 {
182 struct RFCNB_Pkt *pkt;
183 char *hdr;
184 int len;
185
186 /* Plug in the header and send the data */
187
188 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
189
190 if (pkt == NULL) {
191
192 RFCNB_errno = RFCNBE_NoSpace;
193 RFCNB_saved_errno = errno;
194 return (RFCNBE_Bad);
195
196 }
197 pkt->next = udata; /* The user data we want to send */
198
199 hdr = pkt->data;
200
201 /* Following crap is for portability across multiple UNIX machines */
202
203 *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
204 RFCNB_Put_Pkt_Len(hdr, Length);
205
206 #ifdef RFCNB_DEBUG
207
208 fprintf(stderr, "Sending packet: ");
209
210 #endif
211
212 if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
213
214 /* No need to change RFCNB_errno as it was done by put_pkt ... */
215
216 return (RFCNBE_Bad); /* Should be able to write that lot ... */
217
218 }
219 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
220
221 pkt->next = NULL;
222
223 RFCNB_Free_Pkt(pkt);
224
225 return (len);
226 }
227
228 /* We pick up a message from the internet ... We have to worry about
229 * non-message packets ... */
230 int
231 RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
232 {
233 struct RFCNB_Pkt *pkt;
234 // struct RFCNB_Hdr *hdr;
235 int ret_len;
236
237 if (con_Handle == NULL) {
238
239 RFCNB_errno = RFCNBE_BadHandle;
240 RFCNB_saved_errno = errno;
241 return (RFCNBE_Bad);
242
243 }
244 /* Now get a packet from below. We allocate a header first */
245
246 /* Plug in the header and send the data */
247
248 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
249
250 if (pkt == NULL) {
251
252 RFCNB_errno = RFCNBE_NoSpace;
253 RFCNB_saved_errno = errno;
254 return (RFCNBE_Bad);
255
256 }
257 pkt->next = Data; /* Plug in the data portion */
258
259 if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
260
261 #ifdef RFCNB_DEBUG
262 fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
263 #endif
264
265 return (RFCNBE_Bad);
266
267 }
268 /* We should check that we go a message and not a keep alive */
269
270 pkt->next = NULL;
271
272 RFCNB_Free_Pkt(pkt);
273
274 return (ret_len);
275 }
276
277 /* We just disconnect from the other end, as there is nothing in the RFCNB */
278 /* protocol that specifies any exchange as far as I can see */
279 int
280 RFCNB_Hangup(struct RFCNB_Con *con_Handle)
281 {
282
283 if (con_Handle != NULL) {
284 RFCNB_Close(con_Handle->fd); /* Could this fail? */
285 free(con_Handle);
286 }
287 return 0;
288 }
289
290 /* Set TCP_NODELAY on the socket */
291 int
292 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
293 {
294
295 return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
296 (char *) &yn, sizeof(yn)));
297 }
298
299 #if NOT_IMPLEMENTED
300 /* Listen for a connection on a port???, when */
301 /* the connection comes in, we return with the connection */
302 void *
303 RFCNB_Listen()
304 {
305 }
306
307 #endif
308
309 /* Pick up the last error response as a string, hmmm, this routine should */
310 /* have been different ... */
311 void
312 RFCNB_Get_Error(char *buffer, int buf_len)
313 {
314
315 if (RFCNB_saved_errno <= 0) {
316 snprintf(buffer, (buf_len - 1), "%s", RFCNB_Error_Strings[RFCNB_errno]);
317 } else {
318 snprintf(buffer, (buf_len - 1), "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
319 strerror(RFCNB_saved_errno));
320 }
321 }
322
323 /* Pick up the last error response and returns as a code */
324 int
325 RFCNB_Get_Last_Error()
326 {
327 return (RFCNB_errno);
328 }
329
330 /* Pick up saved errno as well */
331 int
332 RFCNB_Get_Last_Errno()
333 {
334 return (RFCNB_saved_errno);
335 }
336
337 /* Pick up the last error response and return in string ... */
338 int
339 RFCNB_Get_Error_Msg(int code, char *msg_buf, int len)
340 {
341 return (strncpy(msg_buf, RFCNB_Error_Strings[abs(code)], len) != NULL);
342 }
343
344 /* Register a higher level protocol print routine */
345 void
346 RFCNB_Register_Print_Routine(RFCNB_Prot_Print_Routine * fn)
347 {
348 Prot_Print_Routine = fn;
349 }